SwoDs
@SwoDs
PHP YII2

Быстрый LIKE по 1 миллиону строк, как быть?

Добрый день, в проекте нужно использовать данные ФИАС-а, когда пользователь начинает набирать название улицы, выводить то что подходит под вводимое, т.е. если набрал "Ленин" ему выдало на выбор Ленинский пр-т, ул. Ленина
Полнотекстовый не подходит, так как слово нужно тогда писать полностью. Как быть, что использовать?
  • Вопрос задан
  • 1728 просмотров
Пригласить эксперта
Ответы на вопрос 10
Sanasol
@Sanasol Куратор тега PHP
нельзя просто так взять и загуглить ошибку
sphinx использовать.
или https://dadata.ru/
Ответ написан
xmoonlight
@xmoonlight
https://sitecoder.blogspot.com
Вначале, все слова записываем в виде хеша так, чтобы буквы шли по-порядку, но повторные - не повторялись. 'мама мыла раму' => 'ма ылру'
Можно дополнительно создать еще один кэш и отсортировать в порядке убывания кол-во повторов букв:
Приведём новый пример: 'мыла раму мама' (переставим слова местами)
'мыла раму мама' => [м-4][ы-1][л-1][а-4][(пробел)-2][р-1][у-1]=>'ма ылру' (предыдущий пример останется без изменений...)
и поиск вести по половинам хэша (при нечетном кол-ве -округляем в большую сторону) введённой строки 'ма ылру':
1. При не найденных совпадениях, порядок такой: 'ма ы'=>'ма'=>'м'
2. При найденных совпадениях, порядок такой: 'ма ылр'=>'ма ыл' Как выдача будет нулевая - берём предыдущий МИНИМАЛЬНЫЙ! результат выдачи.

Таким образом можно отловить с большей вероятностью пропущенные буквы при вводе.

Можно составить отдельную таблицу по всем словам и привязать их к основным данным.

Затем выборка этажеркой:
1. Преобразуем так же вводимую строку и выбираем LIKE 'ма мыл%'
(возможно несколько выборок с проверкой пропущенной буквы) запоминая результат выборки.
2. По этому результату ищем полную строку с тем же LIKE 'мама мыла раму%'
3. При следующем поиске, если хэш не уменьшился и символы в диапазоне длины предыдущего хэша не изменились - мы ищем СРАЗУ ЖЕ! по результату п.1 (и снова запоминаем результат), экономя время (т.е. поиск как бы идёт по предыдущему кэшу).

Таким образом получается, что чем больше букв, тем меньше записей мы перебираем.
А чем меньше мы перебираем, тем больше у нас времени остаётся и мы можем его использовать на дополнительные запросы: для нечеткого поиска.
Ответ написан
Комментировать
www.mysql.ru/docs/man/Fulltext_Search.html

* Звездочка является оператором усечения. В отличие от остальных операторов, она должна добавляться в конце слова, а не в начале.
apple*
... ``apple'', ``apples'', ``applesauce'', и ``applet''.
Ответ написан
Комментировать
Rsa97
@Rsa97
Для правильного вопроса надо знать половину ответа
Если название хранится не как 'ул. Ленина', а как два поля - `name` = 'Ленина', `type` = 'ул', то LIKE 'Лен%' будет использовать индекс по `name`.
Ответ написан
zoonman
@zoonman
⋆⋆⋆⋆⋆
Комментировать
saintbyte
@saintbyte
Django developer
ElasticSearch уже предлагали?
Ответ написан
Комментировать
lxfr
@lxfr
NoSQL?
Ответ написан
Комментировать
opium
@opium
Просто люблю качественно работать
сфинкс
Ответ написан
Комментировать
@Cage
вообщем от все уже написали, резюмирую относительно поиска по мускулю
1. Индексы на parengiud и formalname, причем индекс на название можно ограничить 6-7 символами, искать `parengiud` = '...' AND `formalname` LIKE "%ленин", parentguid в условии поиска ставить первым - так будет быстрее.
2. Полнотекстовый поиск если позволяет движок.

1й вариант даже наверно предпочтительный
Ответ написан
Комментировать
al_gon
@al_gon
solr
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы