Search
Write a publication
Pull to refresh
4
0
Send message

Согласен с моментом - "customer_id в таблице VIP'ов уникален (и вообще, должен быть FK и PK)". И действительно, тогда дистинкт не нужен в подзапросе для join. Для невхождения в данном примере это не будет играть роли, так как запрос всё равно переписывается в антисоединение. Для вхождения в случае с наличием PK на все запросы опять же таки переписываются в одинаковый Nested Loop и не имеют никакой разницы между друг другом. Так что хоть вы и правы в данном моменте, но по сути разницы это не составляет никакой.

Касательно конструкций intersect/except - действительно важное замечание. Я не рассматривал эти примеры лишь потому, что ни разу в своей практике не видел использования этих конструкций в реальном коде. На самом деле это устаревшие конструкции с заведомо проигрышными планами выполнения. Никто это не использует - и правильно делают. Даже на моих примерах:

Нахождение VIP`ов:

20-40 ms у других вариантов против 400+ ms у intersect

Скрытый текст

Нахождение "Кто хоть раз что-то купил":

20-30k ms у других вариантов против 100k+ у intersect:

Скрытый текст

Данные конструкции просто не выдерживают никакой критики и не рекомендуются к использованию никогда и никому.

Мне кажется вы не поняли общее направленность статьи. Я рассмотрел исключительно две типичные ситуации, которые я считаю самыми распространенными. Я не исключаю того, что есть запросы, для которых вышесказанное будет не актуально. Если вы приведете реальный подобный пример для нас всех это будет очень полезный опыт.

Операция дистинкта в случае WHERE IN и WHERE EXISTS не "обязана НЕ присутствовать", а "НЕ обязана присутствовать явно", потому что планировщик будет либо использовать полусоединение, которое подразумевает удаление дубликатов, либо самостоятельно вставит его в план при выборе других инструментов фильтрации (того же join, например). Как мы видим из плана выполнения со скрина, без использования явного дистинкта количество вернувшихся строк совпадает с ожиданиями (800 тыс.)


"тогда как в случае JOIN, наоборот, такая процедура обязательно должна выполняться" - разумеется должна, у нас выполняет соединение один ко многим, фильтровать дубликаты необходимо либо в подзапросе, либо на результирующем сете данных. Если этого не сделать, то на каждую запись из таблицы transactions будет своя запись в результирующем сете. Таким образом, вместо ожидаемых 800 тыс. строк мы получим все (или почти все) 100 млн. Это базовый функционал join.

Без дистинкта в подзапросе
Без дистинкта в подзапросе
С дистинктом (ожидаемый результат)
С дистинктом (ожидаемый результат)

Совершенно правильные замечания с точки зрения казуального юзера, взаимодействующего только с верхними слоями БД. Конечно в отношении "сервис - база данных" не должны участвовать хранимки.
Однако не стоит забывать, что то, что вы видите от БД это лишь верхушка айсберга. Как известно на поверхности находится лишь 1/10 часть.
Само формирование базы не представимо и полностью невозможно без использования хранимок.
Если переводить в метафору - вы, в данном случае, владелец кредитного китайце в пробке, рассуждающий о том, что механическая коробка передач более не нужна и вообще морально устарела. А теперь представьте лицо профессионального гонщика (или Вин Дизеля), который бы это услышал. И вас понять можно, но и глупость, которую вы морозите, сложно оправдать. Не стоит обобщать весь мир АйТи под ваш опыт.

*Смайлик клоуна*

Information

Rating
Does not participate
Registered
Activity