В моем офисе у нас довольно уродливый запрос, но он довольно хорошо работает как в рабочей среде, так и в среде разработки (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.
источник
+1 в разделе Попытка перезаписи комментария к запросу от источника данных.
Мне также интересно, сталкиваетесь ли вы с проблемой разрешений на стороне связанного сервера, ведущей к этому замедлению. Я писал о замедлении работы этого связанного сервера некоторое время назад. Может быть, стоит проверить перми (это сервер, связанный с SQL? Или это другая СУБД? Если последняя, то вы все равно не получите хорошую статистику)
У вас есть SQL Server 2005 в тестовой среде, чтобы попробовать этот запрос и исключить среду?
Вы восстановили статистику после обновления?
источник
С этим сравнением столько проблем ... Я просто не знаю, с чего начать.
Получите точные спецификации для ваших производственных и испытательных машин.
Определите сетевые ссылки между различными связанными серверами в обеих средах. Они одинаковой скорости? Находятся ли серверы рядом друг с другом в обеих средах?
Можно ли вообще переписать запрос, чтобы НЕ использовать связанные серверы? Объединение таблиц между серверами делает вас уязвимым для изменений топологии, и в большинстве случаев это ужасно медленно.
Использование NOT и OR обычно приводит к полному сканированию таблицы. Попробуйте переписать запрос.
источник