Этот баннер — требование Роскомнадзора для исполнения 152 ФЗ.
«На сайте осуществляется обработка файлов cookie, необходимых для работы сайта, а также для анализа использования сайта и улучшения предоставляемых сервисов с использованием метрической программы Яндекс.Метрика. Продолжая использовать сайт, вы даёте согласие с использованием данных технологий».
Политика конфиденциальности
|
|
|
Знатокам оптимизации
|
|||
|---|---|---|---|
|
#18+
Дано: Таблица: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. Запрос: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. Распределение данных в таблице: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. По факту выборка снаружи идет только по полям где SystemName IS NOT NULL и всегда возвращается одна строка, но явно в запросе этого нет. Индекса по SystemName нет (и не может быть из-за типа поля), но есть статистика. Собственно проблема: Запускаю Код: sql 1. , в плане Clustered Index Scan, Number of Rows Read ~ 22600, запрос работает быстро (~ 100 ms). Статистика выглядит вот так Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. Запускаю Код: sql 1. , в плане тоже Clustered Index Scan, но Numbers of Rows Read ~ 5 600 000, запрос резко замедляется (~ 2000 ms). Статистика становится такой Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. Вопрос: почему так? Я понимаю, что sp_updatestats делает маленький семпл (в данном случае 116167), а update statics with fullscan делает полный семпл. Но почему при этом так резко меняется Number of Rows Read, а соответственно и время выполнения запроса? Я как-то думал, что скан - он и есть скан, то есть в любом случае прочитает всё. А так получается, что с лучшей статистикой запрос работает в разы медленнее, парадокс... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.05.2019, 09:56 |
|
||
|
Знатокам оптимизации
|
|||
|---|---|---|---|
|
#18+
OblomНо почему при этом так резко меняется Number of Rows Read, а соответственно и время выполнения запроса?Либо - разные запросы - разные планы - разные опции итератора Clustered Index Scan - разные значения @p__linq__0 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.05.2019, 10:24 |
|
||
|
Знатокам оптимизации
|
|||
|---|---|---|---|
|
#18+
Oblom, покажите Код: sql 1. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.05.2019, 10:38 |
|
||
|
Знатокам оптимизации
|
|||
|---|---|---|---|
|
#18+
invmOblomНо почему при этом так резко меняется Number of Rows Read, а соответственно и время выполнения запроса?Либо - разные запросы - разные планы - разные опции итератора Clustered Index Scan - разные значения @p__linq__0 Да, планы разные, в быстром скане паралеллизм не включается, потому как Estimated Number Of Rows = 2366, а в медленном паралеллизм включается, поскольку Estimated Number Of Rows = 5600990 Запросы и значения параметров одни и те же, картина выглядит просто: update statistics with fullscan - CPU = 100% exec sp_updatestats - CPU = 10% Собственно проблема и появилась после регламентного запуска update statistics with fullscan Вопрос: почему разный семпл в статистике так сильно влияет на Estimated Number Of Rows, а главное на время выполнения запроса. На всякий случай приложу оба плана, может кому-то будет интересно посмотреть. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.05.2019, 10:47 |
|
||
|
Знатокам оптимизации
|
|||
|---|---|---|---|
|
#18+
И "быстрый" план ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.05.2019, 10:47 |
|
||
|
Знатокам оптимизации
|
|||
|---|---|---|---|
|
#18+
OblomИ "быстрый" план ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.05.2019, 10:48 |
|
||
|
Знатокам оптимизации
|
|||
|---|---|---|---|
|
#18+
komradOblom, покажите Код: sql 1. Microsoft SQL Server 2014 (SP3-CU1) (KB4470220) - 12.0.6205.1 (X64) Nov 30 2018 02:59:03 Copyright (c) Microsoft Corporation Enterprise Edition (64-bit) on Windows NT 6.3 <X64> (Build 14393: ) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.05.2019, 10:48 |
|
||
|
Знатокам оптимизации
|
|||
|---|---|---|---|
|
#18+
OblomПо факту выборка снаружи идет только по полям где SystemName IS NOT NULL и всегда возвращается одна строка, но явно в запросе этого нет. Индекса по SystemName нет (и не может быть из-за типа поля), но есть статистика. попробуйте создать фильтрованную статистику по этому полю (is not null) https://blog.sqlauthority.com/2015/04/07/sql-server-what-is-filtered-statistics/ ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.05.2019, 11:06 |
|
||
|
Знатокам оптимизации
|
|||
|---|---|---|---|
|
#18+
komradOblomПо факту выборка снаружи идет только по полям где SystemName IS NOT NULL и всегда возвращается одна строка, но явно в запросе этого нет. Индекса по SystemName нет (и не может быть из-за типа поля), но есть статистика. попробуйте создать фильтрованную статистику по этому полю (is not null) https://blog.sqlauthority.com/2015/04/07/sql-server-what-is-filtered-statistics/ Создал: Код: sql 1. ситуация не поменялась, видимо фильтрованной ему мало и он опять полную использует ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.05.2019, 11:34 |
|
||
|
Знатокам оптимизации
|
|||
|---|---|---|---|
|
#18+
Oblom, для интереса попробуйте OPTION(QUERYTRACEON 4138) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.05.2019, 12:04 |
|
||
|
Знатокам оптимизации
|
|||
|---|---|---|---|
|
#18+
Oblom[/src] ситуация не поменялась, видимо фильтрованной ему мало и он опять полную использует запрос запускали с с option (recompile) ? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.05.2019, 12:07 |
|
||
|
Знатокам оптимизации
|
|||
|---|---|---|---|
|
#18+
Oblom, Раз используете переменную в предикате попробуйте option (recompile) или optimize for @variable= value ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.05.2019, 12:08 |
|
||
|
Знатокам оптимизации
|
|||
|---|---|---|---|
|
#18+
спасибо всем за подсказки с изменением запроса. Однако поменять запрос нетривиальная задача, там коробочное решение и внутрь залезть непросто, плюс сделано всё на LINQ, и по уму надо переписывать на SP или view, чтобы иметь возможность хинтовать. А совсем уж по уму надо переделывать логику приложения, которая сотню раз в секунду долбится в таблицу клиентов, чтобы получить одну из 4 записей с заполненным полем в таблице с 5.5 млн. строк. И просто для этих 4 пользователей сделать отдельную таблицу и кешировать её вызов минут на 5, а то и на час. Я нашел другой выход, сменил тип столбца на nvarchar(50) и повесил туда покрывающий индекс. Но хочется понять, почему величина семпла статистики оказывает такое разрушающее воздействие на план и время выполнения запроса. Больше не меняется ничего, только семпл по которому сделана статистика, ну и гистограмма, которая при этом получается. В "быстрой" гистограмме вообще все значения этого столбца NULL, может в этом дело... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.05.2019, 12:39 |
|
||
|
Знатокам оптимизации
|
|||
|---|---|---|---|
|
#18+
Oblom, кстати да, посмотрел план у вас там собственно в игру вступает row goal. флаг предложенный товарищем TaPaK должен по сути менять вашу ситуацию с быстрым планом. Код: plaintext 1. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.05.2019, 13:22 |
|
||
|
Знатокам оптимизации
|
|||
|---|---|---|---|
|
#18+
Oblom, Ваши планы скомпилированы для @p__linq__0 = 'SearchEngine' Т.к. в одном случае данное значение отсутствует в статистике, а в другом присутствует, получаются разные оценки стоимости. Одна из этих оценок приводит к параллельному плану. И получается эффект, описанный тут - https://www.sql.kiwi/2012/05/parallel-row-goals-gone-rogue.html ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.05.2019, 10:27 |
|
||
|
Знатокам оптимизации
|
|||
|---|---|---|---|
|
#18+
а кто скажет как получилось 22600? в плане без статистики по полю? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.05.2019, 10:33 |
|
||
|
Знатокам оптимизации
|
|||
|---|---|---|---|
|
#18+
До 2014 если значение выходило за границы гистограммы то вычисление селективности останавливалось, начиная с 2014, когда появилась новая модель оценки, которая используется у ТС, сервер пытается что-то с этим сделать. В частности распознает эту ситуацию, как оценка по возрастающему ключу и пытается моделировать исходя из этого предположения (можно выполнить запрос с недокументированным флагом 9489, который отключает AscendingKeyFilter, чтобы убедиться в этом). Увидеть процесс можно, включив флаг трассировки 2363 (не документированный), либо событие xEvent query_optimizer_estimate_cardinality. На примере тестовой таблицы с распределением как у ТС: TF: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. xEvent: Код: xml 1. 2. 3. 4. Пытается моделировать по средней частоте, но т.к. средняя частота 1 (т.е. все значения одинаковые), то вместо этого, считает квадратный корень из числа строк (допущение модели). Код: sql 1. То, что мы видим в плане после округления. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.05.2019, 12:10 |
|
||
|
Знатокам оптимизации
|
|||
|---|---|---|---|
|
#18+
SomewhereSomehow, спасибо! ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.05.2019, 12:16 |
|
||
|
Знатокам оптимизации
|
|||
|---|---|---|---|
|
#18+
Спасибо всем откликнувшимся! буду курить ссылки и пытаться осознать... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.05.2019, 12:48 |
|
||
|
Знатокам оптимизации
|
|||
|---|---|---|---|
|
#18+
SomewhereSomehow, И последний вопрос, почему так время двух запросов так резко разнится? И там и там скан в запросе, и там и там по идее он должен просканировать все строки и занять это должно примерно одинаковое время... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.05.2019, 12:57 |
|
||
|
Знатокам оптимизации
|
|||
|---|---|---|---|
|
#18+
OblomSomewhereSomehow, И последний вопрос, почему так время двух запросов так резко разнится? И там и там скан в запросе, и там и там по идее он должен просканировать все строки и занять это должно примерно одинаковое время... про параллелизм и row goal ссылку уже дали ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.05.2019, 13:20 |
|
||
|
Знатокам оптимизации
|
|||
|---|---|---|---|
|
#18+
TaPaKOblomSomewhereSomehow, И последний вопрос, почему так время двух запросов так резко разнится? И там и там скан в запросе, и там и там по идее он должен просканировать все строки и занять это должно примерно одинаковое время... про параллелизм и row goal ссылку уже дали Всё, понял, спасибо, про параллелизм забыл. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.05.2019, 13:24 |
|
||
|
|

start [/forum/topic.php?fid=46&msg=39815729&tid=1687801]: |
0ms |
get settings: |
6ms |
get forum list: |
15ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
53ms |
get topic data: |
9ms |
get forum data: |
3ms |
get page messages: |
60ms |
get tp. blocked users: |
1ms |
| others: | 281ms |
| total: | 434ms |

| 0 / 0 |
