TGViewer
LEFT JOIN LEFT JOIN @leftjoin · 42K subscribers
Post #1938 17.8K
OR или не OR?
Представим, что у вас есть большая таблица applications, в которой хранятся данные о заявках пользователей, а также о людях, которые их подают (они указаны в столбце submitter_id) или рассматривают (reviewer_id). Вам нужно посчитать, со сколькими заявками взаимодействовал пользователь — неважно, отправлял или рецензировал.
Какой запрос, на ваш взгляд сработает быстрее?
SELECT COUNT(*)
FROM application
WHERE submitter_id = :user_id
OR reviewer_id = :user_id;

или
SELECT (
SELECT COUNT(*) FROM application WHERE reviewer_id = :user_id
)
+ (
SELECT COUNT(*) FROM application WHERE submitter_id = :user_id
)
- (
SELECT COUNT(*) FROM application WHERE submitter_id = :user_id
AND reviewer_id = :user_id
);


Первый вариант выглядит изящнее, да и логичнее — зачем расписывать сложную конструкцию с подзапросами, когда можно обойтись 4 строками. Но при этом второй запрос выполнится почти в 100 раз быстрее. Пруф.

По той же ссылке есть объяснение, почему так получается, но если кратко:
🔵Оператор AND уменьшает выборку данных, а индексы и статистика БД помогают оптимизировать его выполнение. Когда вам нужно отобрать данные по двум условиям, движок ищет сначала ищет записи, где выполняется более редкое условие и затем проходится по второму.
🔵Оператор OR либо последовательно проходится по всем данным в таблице, либо целиком одной колонке, затем по второй, чтобы их объединить. Оба варианта более «дорогие», чем просто просканировать столбец и отфильтровать лишнее

Так что если вы замечаете, что запросы с OR слишком долго выполняются, то имеет смысл их переписать — пусть будут не такие красивые, зато более эффективные. Например, для кейсов, как в начале поста автор рекомендует задуматься о создании «дочерней» таблицы:
CREATE TABLE application_user (
user_id int8 NOT NULL,
application_id int8 NOT NULL,
user_type enum('submitter','reviewer') NOT NULL
);


И свой изначальный запрос переделать через JOIN:
SELECT * FROM application a
JOIN application_user au USING (application_id)
WHERE au.user_id = :user_id;

Это все не повод отказываться от использования OR совсем и в любой непонятной ситуации создавать и джойнить новые таблицы. Но особенности этого оператора стоит иметь в виду, особенно, когда вы работаете с большими объемами данными.
  • ❤ 20
  • 👍 14
  • 🤩 9
  • 🤔 7
  • 🔥 1
More from @leftjoin
  1. Sep 25, 2026Новый ИИ-бенчмарк подвезли Тем, как ИИ пишет код, взламывает сайты или решает математическ…
  2. Sep 23, 2026Как грамотно делегировать задачи ИИ Внедрение искусственного интеллекта и агентов в работу…
  3. Sep 18, 2026Что делать с тепловыми картами и хороплетами? Все виды графиков и чартов по-своему хороши…
  4. Sep 16, 20263D-карты СУБД Отвлечемся от новостей про ИИ и скандалов вокруг OpenAI и посмотрим, что вну…
  5. Sep 14, 2026Решение математических проблем это не просто бенчмарк На прошлой неделе разгорелся серьезн…
  6. Sep 11, 2026Astra смогла, а вы сможете? Мы с вами недавно обсуждали эссе, опубликованное на сайте Open…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →