Что быстрее - INSTR или LIKE? - PullRequest
33 голосов
/ 16 марта 2010

Если ваша цель - проверить, существует ли строка в столбце MySQL (типа 'varchar', 'text', 'blob' и т. Д.), Что из перечисленного ниже быстрее / эффективнее / лучше в использовании и почему

Или есть какой-то другой метод, который превосходит любой из них?

INSTR( columnname, 'mystring' ) > 0

против

columnname LIKE '%mystring%'

Ответы [ 4 ]

48 голосов
/ 16 марта 2010

Поиск в FULLTEXT будет абсолютно быстрым, как отметил Кибибу в комментариях выше.

Однако

mysql> select COUNT(ID) FROM table WHERE INSTR(Name,'search') > 0;
+-----------+
| COUNT(ID) |
+-----------+
|     40735 | 
+-----------+
1 row in set (5.54 sec)

mysql> select COUNT(ID) FROM table WHERE Name LIKE '%search%';
+-----------+
| COUNT(ID) |
+-----------+
|     40735 | 
+-----------+
1 row in set (5.54 sec)

В моих тестах они работают точно так же. Они оба нечувствительны к регистру, и, как правило, они выполняют сканирование полной таблицы, как правило, нет-нет при работе с высокопроизводительным MySQL.

Если вы не выполняете поиск префикса в индексированном столбце:

mysql> select COUNT(ID) FROM table WHERE Name LIKE 'search%';
+-----------+
| COUNT(ID) |
+-----------+
|         7 | 
+-----------+
1 row in set (3.88 sec)

В этом случае LIKE только с подстановочным знаком суффикса намного быстрее.

11 голосов
/ 04 марта 2014

MySQL - INSTR против LOCATE против LIKE против REGEXP

Для меня INSTR и LOCATE показали самые быстрые результаты:

# 5.074 sec
SELECT BENCHMARK(100000000,INSTR('foobar','foo'));

# 5.086 sec
SELECT BENCHMARK(100000000,LOCATE('foo','foobar')); 

# 8.990 sec
SELECT BENCHMARK(100000000,'foobar' LIKE '%foo%');

# 14.433 sec
SELECT BENCHMARK(100000000,'foobar' REGEXP 'foo'); 

# 5.5.35-0ubuntu0.12.10.2 
SELECT @@version;
11 голосов
/ 16 марта 2010

В случае «передней карты» (т. Е. Предиката «LIKE '% ...'»), как здесь имеет место, INSTR и LIKE должны работать примерно одинаково .

Когда подстановочный знак равен , а не"передним подстановочным знаком", подход LIKE должен быть более быстрым, если только подстановочный знак не является слишком избирательным.

Причина , почему тип подстановочного знака и его селективность имеют значение , заключается в том, что предикат с INSTR () систематически приведет к сканированию таблицы (SQL не может делать никаких предположений о семантике INSTR), благодаря чему SQL может использовать свое понимание семантики предиката LIKE, возможно, для использования индекса, чтобы помочь ему только тестировать сокращенный набор возможных совпадений.

Как предлагается в комментарии к самому вопросу, Полнотекстовый индекс будет намного быстрее . Разница зависит от конкретного распределения слов в тексте, а также от общего размера таблицы и т. Д., Но ожидайте чего-либо от вдвое быстрее, может быть, в 10 раз быстрее.

Возможным недостатком использования полнотекстового индекса в дополнение к общим накладным расходам на создание такого индекса является то, что, если только вы не будете очень осторожны при настройке этого индекса (например: определение списка стоп-слов, использование специального синтаксиса поиска, чтобы избежать инфлективные формы и тому подобное ...), могут быть случаи, когда результаты, предоставленные FullText, будут не такими, как ожидалось . Например, в поисках «ПИЛА» (инструмент для резки дерева) можно получить много обращений к записям, включая глагол «видеть» в его различных сопряженных формах.
Конечно, эти лингвистические функции полнотекстовых индексов обычно могут быть переопределены, и также можно считать, что такие функции являются преимуществом, а не недостатком. Я просто упомянул это здесь, так как мы сравниваем это с простым поиском по шаблону.

3 голосов
/ 15 января 2014

К тесту Раззеда добавить нечего. Но очевидно, что использование regexp влечет за собой гораздо большую нагрузку обработки , в отличие от того, что Сет указывает в своем комментарии.

Следующие тесты предполагают, что вы установите query_caching в On в my.ini

query_cache_type = 1
query_cache_size = 64M

Тесты

  • Времена показывают среднюю производительность из трех измерений (с периодической очисткой кэша):

  • LIKE

    SELECT * FROM `domain_model_offers` WHERE `description` LIKE '%inform%' LIMIT 0 , 30
    

    Начальная: 0,0035 с
    Кэшируется: 0,0005 с

  • REGEXP

    SELECT * FROM `domain_model_offers` WHERE `description` REGEXP 'inform' LIMIT 0 , 30
    

    По умолчанию: 0,01 с
    Кэшировано: 0,0004 с

Результат

LIKE или INSTR определенно быстрее, чем REGEXP.

Несмотря на то, что разница в кеше минимальна, она, вероятно, достаточна для дальнейшего расследования.

В вероятно настроенной системе MySQL полнотекстовая индексация обычно должна выполняться быстрее или, по крайней мере, на уровне неиндексированного поиска. Поэтому используйте индексирование, особенно для длинных текстов на человеческом языке, независимо от прерывистого кода разметки.

...