Привет, Хабр! Меня зовут Сергей Барановский, я руководитель проектов по аналитике в Блоке по клиентскому опыту и сервису и сегодня я хочу поделиться наболевшим. Джойн таблиц — одна из самых базовых вещей в аналитике. Казалось бы, допустить здесь ошибку почти невозможно. И правда! Что может быть проще, чем стыковать таблицы ключ к ключу?! Ковыряться в носу и то сложнее — можно ненароком кровеносный сосуд задеть. И, потеряв бдительность из-за простоты процедуры, можно набрать корзину проблем на самых базовых вещах. Под катом — познавательный кейс для тех, кто ходит тропами SQL.
У меня было два датасета, которые я предварительно пропустил через DISTINCT, то есть убрал все дубли. Мне нужно сделать LEFT JOIN. В левой таблице есть NULL-ключи, и я об этом знаю. «Но это не так важно, — подумал я, — ведь в правой таблице нет NULL-ключей, так что левые NULL-ключи останутся одинокими». С такими мыслями я начал джойн здоровенных таблиц.
Время шло, и в моей почте начали скапливаться «письма счастья», предупреждающие о приближении к лимиту WORK.
И вот, несмотря на мои скрещенные пальцы, лимит достигается, очищая WORK, словно Fairy — противень на празднике Вилларриба. Начинается разбор полетов. И оказывается, что я напрасно считал, что в правом датасете не было NULL-ключей. Они еще как были, просто без целенаправленного поиска заметить их среди миллиона строк было довольно сложно. А что случилось, когда парочка NULL-ключей нашла друг друга? Они начали яростно джойниться, тем самым раздувая WORK. Вот как это примерно выглядело:
«Ок, — подумал я, — тогда просто ставлю условие IS NOT NULL на ключи правой таблицы». Сказано — сделано. LEFT JOIN отрабатывает, начинается анализ. И тут я замечаю, что для LEFT JOIN таблица имеет слишком хорошую полноту данных. Начинаю проверять — и правда, данных из левой таблицы, по которым не было совпадений в правой, просто нет. «Но почему? — подумал я. — Я же сделал LEFT JOIN!» Конечно, я сразу сообразил, что дело в условии IS NOT NULL на правой таблице. Но с первого взгляда это выглядело нелогично. Вот как это выглядело в моем мозгу:
Но по факту это было так:
То есть правило SQL таково, что сначала идет JOIN, а после включается WHERE. Таким образом я не только пожрал ресурсы на джойн NULL-ключей, но еще и не получил того, что мне нужно. В итоге я сделал еще один запрос на правую таблицу, отфильтровав NULL-ключи. И только после этого произвел LEFT JOIN.
Вот такая вот история, как можно оступиться на базовых вещах. Берегите место, следуйте правилу бритвы Оккама — не плодите сущности.