Обновление:
Смотрите эту запись в моем блоге для деталей производительности:
SELECT * FROM table WHERE field & number = number
SELECT * FROM table WHERE field | number = number
Этот индекс может быть эффективен двумя способами:
- Чтобы избежать раннего сканирования таблицы (поскольку сравниваемое значение содержится в самом индексе)
- Для ограничения диапазона исследуемых значений.
Ни одно из условий в вышеприведенных запросах не является sargable , этот индекс не будет использоваться для сканирования диапазона (с такими условиями, как сейчас).
Однако точка 1
все еще сохраняется, и индекс может быть полезен.
Если ваша таблица содержит, скажем, 100
байтов на строку в среднем и 1,000,000
записей, то при сканировании таблицы потребуется сканировать 100 Mb
данных.
Если у вас есть индекс (с 4
-байтовым ключом, 6
-байтным указателем строки и некоторыми внутренними издержками), запрос должен будет сканировать только 10 Mb
данных плюс дополнительные данные из таблицы, если фильтр успешен.
- Сканирование таблицы более эффективно, если ваше состояние не является выборочным (у вас высокая вероятность соответствия этому условию).
- Сканирование индекса более эффективно, если ваше условие является выборочным (у вас низкая вероятность соответствия этому условию).
Оба эти запроса потребуют сканирования всего индекса.
Но переписав запрос AND
, вы также сможете извлечь выгоду из ранжирования по индексу.
Это условие:
field & number = number
может соответствовать полям, только если старшие биты из установленного number
установлены и в field
.
И вы должны просто предоставить это дополнительное условие для запроса:
SELECT *
FROM table
WHERE field & number = number
AND field >= 0xFFFFFFFF & ~((2 << FLOOR(LOG(2, 0xFFFFFFFF & ~number))) - 1)
Это будет использовать диапазон для грубой фильтрации и условие для тонкой фильтрации.
Чем больше битов для number
сброшено в конце, тем лучше.