Этот баннер — требование Роскомнадзора для исполнения 152 ФЗ.
«На сайте осуществляется обработка файлов cookie, необходимых для работы сайта, а также для анализа использования сайта и улучшения предоставляемых сервисов с использованием метрической программы Яндекс.Метрика. Продолжая использовать сайт, вы даёте согласие с использованием данных технологий».
Политика конфиденциальности
|
|
|
Как заставить SQL Server ничего не делать, если переменная NULL
|
|||
|---|---|---|---|
|
#18+
Доброе утро. Вот такой запрос: Код: sql 1. 2. 3. 4. 5. Можно ли заставить SQL Server ничего не делать (не сканировать таблицу или искать индексы), если переменная @var является NULL. Поле ID кластеризованный индекс не допускающий NULL Знаю что можно так сделать, если поставить внешнее условие IF. Но можно ли в самом запросе такое провернуть? Спрашиваю из любопытства. Т.е. условно говоря, сервер посмотрел на значение переменной, затем на тип столбца в искомом поле, узнал что поле не допускает NULL и пропускал запрос ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.07.2018, 09:41 |
|
||
|
Как заставить SQL Server ничего не делать, если переменная NULL
|
|||
|---|---|---|---|
|
#18+
Код: sql 1. Впрочем, оптимизатор не настолько идиотичен - никакого scan и seek не будет. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.07.2018, 10:36 |
|
||
|
Как заставить SQL Server ничего не делать, если переменная NULL
|
|||
|---|---|---|---|
|
#18+
План, который тебе нарисовали - это предварительный сферический план в вакууме. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.07.2018, 10:38 |
|
||
|
Как заставить SQL Server ничего не делать, если переменная NULL
|
|||
|---|---|---|---|
|
#18+
aleks222 Код: sql 1. Впрочем, оптимизатор не настолько идиотичен - никакого scan и seek не будет. Код: sql 1. и так означает Код: sql 1. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.07.2018, 11:35 |
|
||
|
Как заставить SQL Server ничего не делать, если переменная NULL
|
|||
|---|---|---|---|
|
#18+
aleks222, авторВпрочем, оптимизатор не настолько идиотичен - никакого scan и seek не будет. разве? Я ведь включил действительный план запроса. Выполнил запрос и он показывает такой вот план. Вообще смущает не только, что сервер делает поиск, но и какое то обновление кластерного индекса. Ведь я индекс совсем не трогаю. Зачем все это? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.07.2018, 11:49 |
|
||
|
Как заставить SQL Server ничего не делать, если переменная NULL
|
|||
|---|---|---|---|
|
#18+
VicNВообще смущает не только, что сервер делает поиск, но и какое то обновление кластерного индекса. Ведь я индекс совсем не трогаю. Зачем все это?Почитайте что такое кластерный индекс, тогда поймете зачем "какое то обновление кластерного индекса". По вашим данным можно только сказать, что на таблицу, помимо ПК, наложены еще ограничения. Если хотите более подробного анализа, покажите полное определение Detail и актуальный план в формате sqlplan. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.07.2018, 12:43 |
|
||
|
Как заставить SQL Server ничего не делать, если переменная NULL
|
|||
|---|---|---|---|
|
#18+
Покажите план в нормальном виде. По фотографиям гадать долго будет. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.07.2018, 12:45 |
|
||
|
Как заставить SQL Server ничего не делать, если переменная NULL
|
|||
|---|---|---|---|
|
#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. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.07.2018, 14:35 |
|
||
|
Как заставить SQL Server ничего не делать, если переменная NULL
|
|||
|---|---|---|---|
|
#18+
VicN, Такая форма плана потому, что есть у таблицы фильтрованный индекс ix_Designation, который зависит от столбца Designation. План отличается от первоначально показанного. Куда дели ограничение, зависящее от Designation? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.07.2018, 15:15 |
|
||
|
Как заставить SQL Server ничего не делать, если переменная NULL
|
|||
|---|---|---|---|
|
#18+
invmVicN, Такая форма плана потому, что есть у таблицы фильтрованный индекс ix_Designation, который зависит от столбца Designation. План отличается от первоначально показанного. Куда дели ограничение, зависящее от Designation? Там было проверочное ограничение check на поля Designation и Name. Удалил, т.к. это ограничение старое и не актуально на данный момент для разрабатываемой мной базы. По моему обсуждение пошло в другую сторону. Изначально я хотел выяснить, есть ли возможность не вынося во внешнее условие IF, сделать проверку переменной на значение NULL и не дергать таблицу и индексы как в плане, если переменная действительно является NULL. Видимо так не получится. Тему можно закрывать ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.07.2018, 15:56 |
|
||
|
Как заставить SQL Server ничего не делать, если переменная NULL
|
|||
|---|---|---|---|
|
#18+
VicNПо моему обсуждение пошло в другую сторону. Изначально я хотел выяснить, есть ли возможность не вынося во внешнее условие IF, сделать проверку переменной на значение NULL и не дергать таблицу и индексы как в плане, если переменная действительно является NULL.По-моему, вы сами поинтересовались почему и зачем такой план. Если желаете проверять значение переменной, то перепишите условие: Код: sql 1. Тогда в плане, перед доступом к таблице (Clustered Index Seek), появится соответствующий фильтр. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.07.2018, 16:06 |
|
||
|
Как заставить SQL Server ничего не делать, если переменная NULL
|
|||
|---|---|---|---|
|
#18+
VicN, Добрый день. В самом запросе можно «провернуть», как уже выше сказали, добавив дополнительно условие «and @var is not null». Это только для помощи оптимизатору, т.к. логически, в данном случае, это одно и то же. Но дополнительный предикат, дает серверу возможность использовать Startup Filter. Это такой вид фильтра, в котором проверяется некоторое выражение (Startup Expression Predicate) и если оно не выполняется, то вся нижележащая/дочерняя ветка плпнп не будет выполняться. Добавьте в запросе в условие where «and @var is not null», и посмотрите в свойствах появившегося оператора фильтра Startup Expression Predicate: [@var] IS NOT NULL. Далее сравните в вашем плане и в получившемся свойство Number of Executions оператора Clustered Index Seek, в первом оно 1, т.е. оператор вызывался, во втором 0, т.е. не вызывался. Хотя на уровне Storage Engine и то, и то не осуществляет доступ к строкам, включите «statistics io», и посмотрите число логических чтений, либо на более поздних версиях, можно посмотреть свойство самого оператора «Actual IO Statistics» и «Number of Rows Read» (которого не будет ни в том, ни в другом случае), можно также посмотреть sys.dm_db_index_operational_stats, чтобы убедиться, что никакого физического доступа нет. В этом смысле сервер не дурак, так что не переживайте, что: «смущает не только, что сервер делает поиск» - он не делает в данном случае (если только вы не отключите ANSI_NULLS и не сделаете колонку nullable, исключив из РК, если так, то разница в физическом доступе будет, и вы это увидите по всем признакам, перечисленным выше). Другое дело, если вы хотите избежать лишних трат на компиляцию, тогда используйте IF. Кроме того, это будет понятнее тем, кто в дальнейшем будет поддерживать код. Далее, по вопросу: «какое то обновление кластерного индекса. Ведь я индекс совсем не трогаю. Зачем все это?» Операция обновления в SQL Server всегда состоит из двух частей - Read Cursor (не тот, не пользовательский курсор, а внутри сиквела, цикл по строкам), и Write Cursor. Один набирает строки для модификации (например, Clustered Index Seek), другой модифицирует (например, Clustered Index Update). В некоторых простых случаях, сервер, умеет это сворачивать в один оператор: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. Планы имеют, кроме корневого элемента (INSERT/UPDATE/DELETE), всего по одному оператору плана, который совмещает Write + Read курсоры. Это работает для самых простых случаев. И даже для них, можно отключить эту оптимизацию недокументированным флагом 8758. Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. Тогда планы такие, какие должны быть без дополнительной оптимизации. Вывод из этого такой: более-менее сложные запросы обновления должны так или иначе содержать в себе часть Read (которая не обязательно получает доступ к строкам, это может быть просто Constant Scan) и часть Write – такова особенность внутренней реализации сиквела. Так что ваш план содержит Update не потому, что он реально что-то обновляет если NULL, а by design. Это обусловлено тем, что несмотря на то, сколько строк затрагивает запрос, сервер должен еще корректно отрабатывать блокировки. Попробуйте в двух окнах, в первом: Код: sql 1. 2. 3. Во втором: Код: sql 1. Несмотря на то, что оба запроса не затрагивают никаких строк по условию 1=0, все равно второй будет заблокирован и будет ждать, пока вы не закончите транзакцию первого. А т.к. итераторы выполнения (не только update, но и все остальные) должны корректно работать с блокировками, логика запроса не единственное, что обуславливает их физический дизайн. Подытоживая, - В данном примере лишнего физического доступа не будет, если он реально не нужен. - Форма плана и наличие тех или иных оператор обусловлена особенностями физической реализации, которые должны учитывать много других аспектов работы, кроме логической составляющей запроса. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.07.2018, 19:33 |
|
||
|
Как заставить SQL Server ничего не делать, если переменная NULL
|
|||
|---|---|---|---|
|
#18+
SomewhereSomehow, Спасибо за развернутый ответ, буду по немного разбираться и обдумывать. Остальным также спасибо за участие в обсуждении ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.07.2018, 21:55 |
|
||
|
|

start [/forum/topic.php?fid=46&msg=39670993&tid=1689452]: |
0ms |
get settings: |
8ms |
get forum list: |
15ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
52ms |
get topic data: |
9ms |
get forum data: |
2ms |
get page messages: |
65ms |
get tp. blocked users: |
2ms |
| others: | 238ms |
| total: | 397ms |

| 0 / 0 |
