Как стать автором
Обновить

Комментарии 18

Спасибо большое за ликбез, позновательно

У меня есть вью с объединением внутри. Что я делаю не так? Явно определяю список колонок вместо звёздочки?


А вообще-то, когда меня учат использовать недокументированные возможности (по аналогии с чёрной и белой магией программирования, когда всё по правилам, но тщательно укрыто под капотом, я назвал бы это шаманством), у меня в мозгу звенит звонок и нервно мигает лампочка.


Возможно, это может быть полезно на проекте, который работает ровно в одном месте, с определёнными, но не известными настройками и набором данных. А когда, как у меня, куча филиалов, разные данные и разные версии (последний sql 2000) вынесли из эксплуатации пару месяцев назад), главное правило — будь проще и конкретнее. Проси у сервера именно то, что тебе надо, а не "то, как, может быть, но это не точно, сервер хотел бы видеть мой запрос".

Материализовать. Материализовать view с union нельзя.
А с or — можно.

Совсем недавно достаточно глубоко тестировал SQL сервера на предмет работы их оптимизаторов. И нет, в таких простых случаях они (а особенно MS SQL сервер) не ошибаются. У автора скорее всего проблема со статистикой.

Хотя в целом конкретно MS SQL из-за особенностей хранения любит сваливаться в Clustered Index Scan, так как он в обычных индексах хранит значение именно из Clustered Index, и ему нужно по сути два раза поиск делать (в том же PostgreSQL не надо, но там и другие проблемы из-за этого). Но если MS SQL в итоге переходит на Clustered Index Scan, то как правило так на самом деле не сильно медленнее.
Скорее у автора какой-то частный случай, где получилось так, что данных ProtuctID = 750 или ProtuctID = 953 было не так много, чтобы sql server в плане использовал index scan. При этом совокупный объем ProtuctID = 750 и ProtuctID = 953 был для этого достаточен

Для того, чтобы не делать "два раза поиск" (видимо, имеется ввиду index seek + key lookup) — в MSSQLSEVER имеются покрывающие индексы.
Это когда часть информации хранится в самом индексе. По факту — эта такая рядомлежащая теневая табличка, с узким подмножеством полей из основной таблицы с другим кластерным индексом.
Разумеется, наличие покрывающих индексов удорожает операции модификации данных, но позволяет иногда ускорить селекты на пару-тройку порядков.
Общее правило: увидел seek + lookup в плане — посмотри, какие поля подтягиваются в лукапе. Иногда энжин не хватает буквально одного — двух полей.
Добавьте их в include индекса, если это не сделает индекс слишком тяжелым, и, возможно, производительность вашего запроса вырастет.
… На пару порядков.

у меня был опыт, когда запрос ускорился в разы просто добавлением скобок в условие. почему так вышло, разбираться не стал. например:
вместо WHERE ProductID = 750 OR ProductID = 953
сделал WHERE ((ProductID = 750) OR (ProductID = 953))
Здесь скорее всего произошел случай, описанный выше. В первом случае был план с index scan, во втором случае с index seek. Версия SQL Server была какая?
старая. 2005. 9.0.5000
В 2008 вроде все корректно ) Может проблема была в неактуальной статистике?

Буквально на днях в статье про стендапы в Яндекс.Такси обсуждался такой кейс.

Но ведь с увеличением степени параллелизма растёт и параллельное обращение к диску.
Если нагрузка уже упёрлась в диск (или близко к этому) — то пользы не будет.
речь не про параллелизм, а про то, что в первом случае сервер сканирует всю таблицу, во втором — ищёт по индексу только подходящие строки.

в целом я согласен с мнением, высказанным выше: кривая статистика, и только.

P.S. уровень оригинальной статьи очень слабый, я надеялся увидеть тут интересные случаи, в которых оптимизатор не справляется, а union помогает направить его в нужное русло, а тут…
Ну не всю таблицу сканирует, а только колонки с индексами — index scan, если бы сканировал всю таблицу, то в плане был бы table scan
Я не особый специалист в ms sql, но AFAIK в случае, если таблица кластеризована, clustered index и есть таблица

Ну, не все йогурты одинаково полезны.
При использовании union вместо or или in — вы рискуете получить избыточную дедубликацию результирующей выборки.
Так что нужно отчетливо понимать, что и зачем вы делаете.
Впрочем, как и всегда в жизни.
:-)
И, кстати, столкнувшись с подобным поведением запроса, прежде чем резать его пополам (хотя это частенько бывает нужно) — обновите статистику. Может странности и пройдут.

на этот случай есть union all. впрочем, не могу не согласиться с «нужно отчетливо понимать, что и зачем вы делаете»
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории