У моєму офісі у нас є запит, який досить некрасивий, але працює досить добре у виробництві та в середовищі розробки (20 сек. Та 4с. Відповідно). Однак у нашому тестовому середовищі це займає понад 4 години. SQL2005 (+ останні патчі) працює у виробництві та розробці. SQL2008R2 працює в тестуванні.
Я переглянув План запитів, і він показує, що SQL2008R2 використовує TempDB за допомогою табличної котушки (ледачої котушки) для зберігання повернених рядків із пов'язаного сервера. Наступним кроком буде показ вкладених циклів (лівий анти-напівз'єднання), що з'їдає 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?
:: EDIT :: Я застосував SP1 та CU3 до обох екземплярів 2008R2, досі немає кісток. Я спеціально встановив колокацію на пов'язаному сервері, без кісток. Я спеціально встановив дозволи мого користувача діяти як sysadmin в обох випадках, без кісток. Я також запам'ятав внутрішні внутрішні файли свого сервера sql 2008 та усунення несправностей, ми побачимо, чи можу я відстежити це як-небудь.
Дякуємо всім за допомогу та поради.
:: EDIT :: Я вносив різні зміни дозволу на пов'язаний сервер. Я використовував входи в SQL, реєстрацію в домені, вводив себе в одиницю користувачів, використовував параметр "бути зробленим за допомогою цього контексту безпеки". Я створив користувачів з обох сторін пов'язаного сервера, які мають права sysadmin на сервері. Я поза ідеями.
Я все одно хотів би дізнатися, чому SQL2005 виконує запит, який настільки різко відрізняється від SQL2008R2. Якби запит був поганим, я б бачив час роботи +4 години на SQL2005 та SQL2008R2.