Каталог решений - Избавиться от скана таблицы в плане запроса

Избавиться от скана таблицы в плане запроса

Избавиться от скана таблицы в плане запроса

В наличии

Для запросов, содержащих «LIKE %СтрокаПоиска%». Справедливо для MS SQL и Postgres.

Категория:

Описание

Введение

Когда в таблице мало строк, затраты на ее сканирование несущественны, а для поиска в "больших таблицах" лучше использовать индексы. Есть как минимум один класс задач, когда бинарные индексы де-факто не помогают. Поиск по условию "LIKE %СтрокаПоиска" или "LIKE %СтрокаПоиска%" фактически равносилен скану таблицы. Например, поиск по телефонным номерам, поиск по номерам документов чаще всего происходит по последним символам.

 

Одно из возможных решений (приводилось на вебинаре Виктора Богачева)

Если для колонки таблицы планируется использовать поиск с условием "LIKE %СтрокаПоиска1", то нужно создать вспомогательную колонку, содержащую "инвертированные" данные исходной колонки. Вспомогательную колонку индексировать. Поиск производить по "инвертированному" значению, при этом условие поиска примет вид "LIKE СтрокаПоиска2%". Например, если СтрокаПоиска1 = "56789", то СтрокаПоиска2 = "98765".

 

Конкретный пример

Обратились пользователи: форма поиска контрагентов работает о-о-очень медленно. Всегда используется условие «LIKE %Строка поиска%» (провоцирует сканирование) для заполненных полей.

 

 

"Универсальную" кнопку переделал в список условий поиска, которые используют индекс. Медленную процедуру оставил для совместимости.

 

 

Пользователю необходимо одновременно искать контрагента по контактным данным, контактным данным партнера, контактным лицам. Это разные таблицы СУБД, кроме номеров телефона они содержат другую информацию. Один и тот же номер телефона может быть записан в разных форматах, расстановка символов "(, ), -, +" изменяется. По описанным причинам, индекс полнотекстового поиска не подходит. К тому же бинарный индекс занимает меньше места.

Почему выбраны последние цифры телефона? Например, выдуманный телефон 5-67-89, из соседнего села 8(243)56-789, из соседней области +7(395243)56-789, (моя малая Родина — привет землякам!) из соседней страны еще более сложный, но оканчивается также. Именно поэтому используют поиск телефона по последним цифрам. В СУБД поиск с условием «LIKE %56789» вызовет по факту сканирование таблицы, скорость О(N). Используем один из вариантов решения, разбиравшийся на вебинара Виктора Богачева вспомогательный регистр МОЙ_ПоискТелефонов, хранит "инвертированные" номера контрагентов. Измерения — "ОбратныйНомер, ВладелецТелефона". Регистр заполняется по существующим номерам и обновляется при изменении телефонов из форм справочников Контрагенты, Партнеры, Контактные лица. Например: для телефона +8(395243)56-789 храним в таблице номер 987653425938. При поиске телефона переворачиваем его, убираем нечисловые символы. Ищем с условием «LIKE 98765%». Значение 98765 находится по бинарному индексу, скорость О(logN). Если в таблице N=1024 записей, то logN = 10, ускорение в сто раз.

 

Заключение

Помните, что поиск по условию «LIKE %Строка поиска» (равносильно сканированию) всегда можно привести к поиску по условию «LIKE Строка поиска%» (использует индекс). Решения для «LIKE %Строка поиска%» также существуют и на вебинаре также рассматриваются.

 

has been added to your cart:
Оформление заказа