Страницы

Поиск по вопросам

четверг, 1 ноября 2018 г.

Как обрабатываются запросы к БД с несколькими условиями?

Подскажите пожалуйста: если в запросе несколько условий, например, WHERE a=1 AND b=2, то сначала выбираются данные, удовлетворяющие условию a=1, а потом среди них выбираются данные по условию b=2? Или для второго условия поиск идет опять по всей таблице? Целесообразен, конечно, первый вариант, но что-то нигде не нашел явного подтверждения.


Ответ

Зависит от индексов и изобретательности оптимизатора. Ну и надо понимать, что разработчики базы, как правило, достаточно опытные люди.
Проверить всё это можно, запустив EXPLAIN вашего запроса.
Если индексов на эти поля нет
...то надо принять решение: делать по две проверки в одном проходе или два прохода по одной проверке. Если данные целиком помещаются в кэше процессора (почти нереальный случай), то разница заметна не будет.
Если не помещаются, то в кэш будут последовательно загружаться разные участки проверяемого набора данных из оперативной памяти (если набор данных туда помещается). Загрузка в кэш занимает какое-то микровремя, но оно становится тем больше, чем больше таблица. Делать два прохода выходит уже дороже: на прежний объём сравнений нужно сделать вдвое больше загрузок в кэш.
Если данные не помещаются даже в оперативную память, всё совсем очевидно — загрузка с диска очень долгая. Настолько, что остальные части запроса вряд ли будут заметны, и выполнение двух обходов, скорее всего, примерно вдвое увеличит время выполнения запроса.
Итог: обход один, две проверки на каждый ряд выглядят рациональнее со всех сторон.
Если есть индекс на одном из полей
...то всё очевидно: сходу есть возможность "дёшево" (по ресурсам) сократить перебираемый набор данных до части таблицы с заданным значением в проиндексированном поле. А уже по этому набору выполнить последовательный перебор и проверить второе условие.
Если есть индексы на двух полях
...то  фиг  EXPLAIN его знает! Более достоверного ответа никто не даст, каждая БД решает этот вопрос как-то по-своему.
Оптимизатор может посмотреть в оба индекса, прикинуть где последовательный перебор окажется меньше и использовать его. А может ошибиться и взять не тот, руководствуясь какими-то своими соображениями.
PostgreSQL умеет делать bitmap scan, в ходе которого он сканирует оба индекса и составляет карту (bitmap) по каждому условию, а затем объединяет две карты в одну согласно условиям, получая результат. Но делать ли это, решает оптимизатор
В идеале: если есть индекс по парам значений
Здесь индекс просто используется напрямую, поэтому порядок поиска будет совпадать с порядком индексирования: сначала спуск с "верхних уровней индекса" (по первому выражению), а затем спуск по второму и сразу получает ответ
Но всё это неважно, если...
данных совсем мало небольшие объёмы данных может быть быстрее обойти без индекса оптимизатор облажается (что бывает) отладка чего превращается в охоту за индексами путём чтения EXPLAINов

Комментариев нет:

Отправить комментарий