J'extrais une grande quantité de données via un serveur lié à partir de VIEWS. J'utilise SQL Server 2012 et le serveur lié est SQL Server 2008
Ma déclaration choisie est
SELECT * INTO MY_LOCAL_TABLE
FROM
( SELECT * FROM LINKEDSERVER.DB.TABLE.VIEW
WHERE DATE>'2012-01-01' AND ID IN (SELECT ID FROM MY_LOCAL_VIEW)
) Q
Je m'attends à 300K lignes pour près de 700 ID. avant, cela prenait quelques heures, mais maintenant, il faut plus de 20 heures !!
Pourriez-vous s'il vous plaît suggérer une solution alternative pour cette douleur ??
Merci beaucoup d'avance!
Lorsque vous utilisez un nom en 4 parties tel que [server].db.dbo.table
, en particulier dans une join
, le tableau entier est souvent copié par le fil sur la machine locale, ce qui n'est évidemment pas idéal.
Une meilleure approche consiste à utiliser une variable OPENQUERY
, gérée à la source (serveur lié).
Essayer:
SELECT *
FROM OPENQUERY([LINKEDSERVER], 'SELECT * FROM DB.TABLE.VIEW WHERE DATE>'2012-01-01')
AND ID IN (SELECT ID FROM MY_LOCAL_VIEW)
Avec cette approche, le serveur lié renverra toutes les lignes pour date> x, puis le serveur local filtrera cela par ID dans votre table locale.
Bien sûr, l’indexation jouera toujours un facteur pour faire SELECT * FROM DB.TABLE.VIEW WHERE DATE>'2012-01-01
.
Une autre approche, que j'utilise pour les grands sous-ensembles, consiste à transférer les identifiants locaux sur le serveur distant, puis à gérer tout cela à distance, par exemple:
-- copy local table to linked server by executing remote query
DECLARE @SQL NVARCHAR(MAX)
SET @SQL = 'SELECT ID INTO db.dbo.tmpTable FROM [SERVER].DB.DBO.MY_LOCAL_VIEW'
EXEC(@SQL) AT [LINKEDSERVER]
-- index remote table?!?
DECLARE @SQL NVARCHAR(MAX)
SET @SQL = 'CREATE INDEX [IXTMP] ON db.dbo.tmpTable (ID)'
EXEC(@SQL) AT [LINKEDSERVER]
-- run query on local machine against both remote tables
SELECT *
-- INTO sometable
FROM OPENQUERY([LINKEDSERVER], 'SELECT *
FROM DB.TABLE.VIEW
WHERE DATE>''2012-01-01''
AND ID IN (SELECT ID FROM db.dbo.tmpTable)')
-- now drop remote temp table of id's
DECLARE @SQL NVARCHAR(MAX)
SET @SQL = 'DROP TABLE db.dbo.tmpTable'
EXEC(@SQL) AT [LINKEDSERVER]
Si la vue locale est également grande, vous pouvez alors envisager d'exécuter une requête distante qui utilise une requête ouverte sur la machine locale (en supposant que la machine distante utilise le lien local).
-- copy local table to linked server by executing remote query
DECLARE @SQL NVARCHAR(MAX)
SET @SQL = 'SELECT ID INTO db.dbo.tmpTable FROM OPENQUERY([SERVER], ''SELECT ID FROM DB.DBO.MY_LOCAL_VIEW'')'
EXEC(@SQL) AT [LINKEDSERVER]
D'autres ont déjà suggéré l'indexation. Donc je ne vais pas là-bas. suggérer une autre option, si vous pouviez changer cette requête interne
SELECT * FROM LINKEDSERVER.DB.TABLE.VIEW
WHERE DATE>'2012-01-01' AND ID IN (SELECT ID FROM MY_LOCAL_VIEW)
Pour une requête joined
utilisant inner join
puisque vous avez dit avoir plus de 700 éléments inlist. Essaie.
SELECT lnv.* FROM LINKEDSERVER.DB.TABLE.VIEW lnv
inner join MY_LOCAL_VIEW mcv
on lnv.ID = mcv.ID
and lnv.DATE > '2012-01-01'