В моем офисе у нас довольно уродливый запрос, но он довольно хорошо работает как в рабочей среде, так и в среде разработки (20 с и 4 с соответственно). Однако в нашей тестовой среде это занимает более 4 часов. SQL2005 (+ последние исправления) запущен в производстве и разработке. SQL2008R2 работает в тестировании.
Я взглянул на план запросов, и он показывает, что SQL2008R2 использует TempDB, используя Table Spool (ленивый спул) для хранения возвращаемых строк со связанного сервера. Следующий шаг показывает, что Nested Loops (левое анти-полусоединение) истощает 96,3% запроса. Линия между двумя операторами составляет 5 398 МБ!
План запроса для SQL 2005 не показывает использование базы данных tempdb и не использует левое анти-полусоединение.
Ниже приведен очищенный код и план выполнения сверху 2005 года, а 2008R2 снизу.
Что вызывает резкое замедление и изменение? Я ожидал увидеть другой план выполнения, так что это не беспокоит меня. Драматическое замедление во времени запроса - вот что беспокоит меня.
Нужно ли мне смотреть на базовое оборудование, так как версия 2008R2 использует базу данных tempdb, мне нужно взглянуть на то, как оптимизировать использование этого?
Есть ли лучший способ написать запрос?
Спасибо за помощь.
INSERT INTO Table1_GroupLock (iGroupID, dLockedDate)
SELECT
Table1.iGroupID,
GETDATE()
FROM Table1
WHERE
NOT EXISTS (
SELECT 1
FROM LinkedServer.Database.Table2 Alias2
WHERE
(
Alias2.FirstName + Alias2.LastName = dbo.fnRemoveNonLetter(Table1.FullName)
AND NOT dbo.fnRemoveNonLetter(Table1.FullName) IS NULL
AND NOT Alias2.FirstName IS NULL
AND NOT Alias2.LastName IS NULL
) OR (
Alias2.FamilyName = dbo.fnRemoveNonLetter(Table1.FamilyName)
AND Alias2.Child1Name = dbo.fnRemoveNonLetter(Table1.Child1Name)
AND NOT dbo.fnRemoveNonLetter(Table1.FamilyName) IS NULL
AND NOT dbo.fnRemoveNonLetter(Table1.Child1Name) IS NULL
AND NOT Alias2.Familyname IS NULL
AND NOT Alias2.Child1Name IS NULL
) OR (
Alias2.StepFamilyName = dbo.fnRemoveNonLetter(Table1.StepFamilyName)
AND Alias2.StepFamilyNameChild1 = dbo.fnRemoveNonLetter(Table1.StepFamilyNameChild2)
AND NOT Alias2.StepFamilyName IS NULL
AND NOT Alias2.StepFamilyNameChild1 IS NULL
AND NOT dbo.fnRemoveNonLetter(Table1.StepFamilyName) IS NULL
AND NOT dbo.fnRemoveNonLetter(Table1.StepFamilyNameChild2) IS NULL
)
) AND NOT EXISTS (
SELECT 1
FROM Table3
INNER JOIN Table4
ON Table4.FirstNameType = Table3.FirstNameType
INNER JOIN table5
ON table5.LastNameType = Table3.LastNameType
WHERE
Table3.iGroupID = Table1.iGroupID
AND Table3.bIsClosed = 0
AND Table4.sNameTypeConstant = 'new_lastname'
AND table5.sFirstNameConstant = 'new_firstname'
)
:: EDIT :: Выполнял запрос из другого экземпляра SQL2005, в основном того же плана выполнения, что и «хороший». Все еще не уверен, как две версии 2005 работают лучше на связанном сервере 2008R2, чем экземпляры 2008R2 для экземпляров 2008R2.
Хотя я не отрицаю, что код мог использовать какую-то работу, если бы это был код, являющийся проблемой, разве я не увидел бы одинаковые планы exec во всех моих испытаниях? Независимо от версии SQL?
:: РЕДАКТИРОВАТЬ :: Я применил SP1 и CU3 к обоим экземплярам 2008R2, но все еще не играли в кости. Я специально установил коллокацию на связанном сервере, без игры в кости. Я специально установил разрешения моего acct пользователя для sysadmin в обоих случаях, без игры в кости. Я также вспомнил о своих внутренних проблемах и устранении неполадок в sql server 2008, посмотрим, смогу ли я как-нибудь это отследить.
Спасибо всем за помощь и советы.
:: РЕДАКТИРОВАТЬ :: Я сделал различные изменения разрешений для связанного сервера. Я использовал SQL логины, доменные логины, я выдавал себя за других пользователей, я использовал опцию «be made with this context». Я создал пользователей на обеих сторонах связанного сервера, которые имеют права sysadmin на сервере. У меня нет идей.
Я все еще хотел бы знать, почему SQL2005 выполняет запрос так резко отличается от SQL2008R2. Если бы это был неправильный запрос, я бы увидел время выполнения 4 часа на SQL2005 и SQL2008R2.