Чому мій індекс може шукати оцінку потрібної кількості рядків, а оператор сортування не може?


11

У мене є запит, який використовує функцію присудка, приблизно так:

commentType = 'EL'
AND commentDateTime >= DATEADD(month,datediff(month,0,getdate()) - 13,0)

У мене відфільтрований індекс в commentType, який має 40K рядків, і коли я запускаю запит, орієнтовна кількість рядків для пошуку шукає дуже точно (близько 11 К), але для наступного кроку (оператор сортування) він повністю ігнорує статистику та просто оцінює загальну кількість рядків у відфільтрованому індексі.

Чому це відбувається? Я знаю основи здібності , і я протестував лише заради розумності, замінивши дату на фактичну дату (01.01.2014) та вуаля ... Сорт почав правильно вгадувати кількість рядків ...

Чому це відбувається і як я можу це виправити? Я не можу пройти фіксовану дату ...


DATEADD(month,datediff(month,0,getdate()) - 13,0)не має для мене сенсу. Що ви намагаєтеся зробити з цим? Чи можна це вдосконалити / спростити?
Даніель Хатмахер

2
@Daniel Це початок місяця, 13 місяців тому.
Аарон Бертран

1
Крім того, відредагуйте своє запитання, щоб відображати версію SQL Server (?), На якій ви працюєте. Використовуйте для цього теги.
Даніель Хатмахер

Чи можете ви спробувати DATEADD(month, -13, DATEADD(day, 1-DATEPART(day, SYSDATETIME()))переконатися, чи є різниця?
Даніель Хатмахер

Якщо у вас індекс без фільтру (commentType, commentDate), він поводиться краще? Просто відфільтровані індекси іноді можуть подавати неправильні оцінки в різних точках планів. Оцінка виглядає як вихід, повідомляючи загальну кількість у відфільтрованому індексі, але насправді план відображається неправильно.
Роб Фарлі

Відповіді:


9

Я вважаю, що ваші оцінки неправильні через помилку в оцінці, яка міняє два аргументи DATEDIFF. Я говорю про це тут:

Приблизним способом є обчислення першого дня 13 місяців тому без використання DATEDIFF (2008+):

DATEADD(MONTH, -13, DATEADD(DAY, 1-DATEPART(DAY,GETDATE()), CONVERT(DATE, GETDATE()));

Я не впевнений, що це стосуватиметься оцінки (я не перевіряв відфільтровані індекси, і я не впевнений, що власне робить сорт або чому він має іншу оцінку без плану та / або решти запитів ).

Виправлення Microsoft рекомендує використовувати TF 4199, але я не дуже впевнений, що для цього вам потрібно:

Іншим варіантом буде переконатися, що ви користуєтеся останньою версією SP / CU для будь-якої версії SQL Server, яку ви використовуєте, оскільки вони стверджують, що це зафіксовано в наступній статті KB (хоча це все ще вимагатиме використання TF 4199 якщо ви не 2014 рік або вище):

Виправлення можна отримати за допомогою таких збірок:

  • 2005 SP3 CU 15 (> = 9.00.4325 І <= 9.00.4999)
  • 2005 SP4 CU 2 (> = 9.00.5259)
  • 2008 SP1 CU 13 (> = 10.00.2816.00 І <= 10.00.3999)
  • 2008 SP2 CU 3 (> = 10.00.4279.00 І <= 10.00.5499)
  • За розширенням 2008 року SP3 та SP4 (> = 10.00.5500)
  • 2008 R2 CU 7 (10.50.1777.0)
  • 2008 R2 SP1 CU 3 (> = 10.50.2769.0 AND <= 10.50.3999)
  • За розширенням 2008 R2 SP2 та SP3 (> = 10.50.4000)
  • За розширенням 2012, 2014, 2016 (> = 11,0)

(Наступного разу, будь ласка, включіть результати SELECT @@VERSIONсвого запитання.)

Зауважу, що у статті КБ йдеться про те, що DATEDIFF може занижувати кількість рядків, що є протилежним тому, що відбувається у вашому сценарії. Це не означає, що виправлення не стосуються вас; Я думаю, що формулювання статті KB є неточним, оскільки оцінки можуть йти в будь-якому напрямку залежно від даних та діапазону, який ви шукаєте.

Мій допис у блозі вище підтвердив, що заміна більше не відбувається в 2014 році. Щоб бути безпечним, я, ймовірно, просто видаляю DATEDIFF з вашого предиката і використовую інший метод, щоб обчислити початок діапазону. Я не пропоную надмір 4199 або використання динамічного SQL для запобігання поганого заміни.


Дякую за допомогу ! Я спробував вашу пропозицію, і план змінився. Ось як це було раніше: s16.postimg.org/t5j6o1yed/fix_wrong.png Ось як це відбувається після того, як я змінив свою дату на ваш: postimg.org/image/5f725rj83 Я буду читати всі URL-адреси, які ви мені дали . Ура.
MrKudz
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.