SQL Linked серверный запрос очень медленный

Я извлекаю большой объем данных через связанный сервер из VIEWS. Я использую SQL Server 2012, а связанный сервер - это SQL Server 2008

Мой оператор select

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

Я ожидаю 300K строк для почти 700 + ID. прежде чем он использовал пару часов, но теперь он занимает более 20 часов!

Не могли бы вы предложить любое альтернативное решение для этой БОЛИ???

Очень большое спасибо!

Ответ 1

Когда вы используете имя из 4 частей, например [server].db.dbo.table, особенно в join, часто время, когда вся таблица копируется по проводу на локальный компьютер, что явно не идеально.

Лучшим подходом является использование OPENQUERY - который обрабатывается в источнике (связанном сервере).

Try:

SELECT *
FROM OPENQUERY([LINKEDSERVER], 'SELECT * FROM DB.TABLE.VIEW WHERE DATE>'2012-01-01')
AND ID IN (SELECT ID FROM MY_LOCAL_VIEW) 

При таком подходе связанный сервер вернет все строки для даты > x, а затем локальный сервер будет фильтровать это по идентификатору в вашей локальной таблице.

Конечно, индексирование по-прежнему будет служить фактором для выполнения SELECT * FROM DB.TABLE.VIEW WHERE DATE>'2012-01-01.

Другим подходом, который я использую для больших подмножеств, является сброс локального идентификатора на удаленный сервер, THEN обрабатывать его удаленно, например:

    -- 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]

Если локальное представление также велико, вы можете рассмотреть возможность выполнения удаленного запроса, который использует openquery обратно на локальный компьютер (при условии, что удаленный компьютер имеет локальную ссылку).

-- 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]

Ответ 2

Другие уже предложили проиндексировать. Поэтому я не пойду туда. предложите другой вариант, если вы можете изменить этот внутренний запрос

 SELECT * FROM LINKEDSERVER.DB.TABLE.VIEW
 WHERE DATE>'2012-01-01' AND ID IN (SELECT ID FROM MY_LOCAL_VIEW)

К запросу joined с использованием inner join, так как вы сказали, что у него есть более 700 элементов списка. попробуйте.

   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'