web-dev-qa-db-fra.com

Quel est le plus rapide - INSTR ou LIKE?

Si votre objectif est de tester si une chaîne existe dans une colonne MySQL (de type 'varchar', 'text', 'blob', etc.), laquelle des options suivantes est plus rapide/plus efficace/meilleure à utiliser, et pourquoi?

Ou, existe-t-il une autre méthode qui surmonte l'un ou l'autre?

INSTR( columnname, 'mystring' ) > 0

contre

columnname LIKE '%mystring%'
36
Grekker

Les recherches FULLTEXT vont être absolument plus rapides, comme l'a noté kibibu dans les commentaires ci-dessus.

Cependant:

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)

Dans mes tests, ils fonctionnent exactement de la même manière. Ils sont tous deux insensibles à la casse, et généralement ils effectuent des analyses de table complète, un non-non général lorsqu'il s'agit de MySQL hautes performances.

Sauf si vous effectuez une recherche de préfixe sur une colonne indexée:

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

Dans ce cas, le LIKE avec seulement un joker de suffixe est beaucoup plus rapide.

50
razzed

MySQL - INSTR vs LOCALISER vs COMME vs REGEXP

Pour moi, les INSTR et LOCALISER ont été les plus rapides:

# 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;
14
pdolinaj

Dans le cas d'une "carte wil avant" (c'est-à-dire un prédicat "LIKE '% ...'") comme cela semble être le cas ici, INSTR et LIKE devraient avoir à peu près les mêmes performances.

Lorsque le caractère générique n'est pas un "caractère générique avant", l'approche LIKE devrait être plus rapide, à moins que le caractère générique ne soit pas très sélectif.

La raison pourquoi le type de caractère générique et sa sélectivité sont importants est qu'un prédicat avec INSTR () entraînera systématiquement un tableau scan (SQL ne peut faire aucune hypothèse sur la sémantique de INSTR), grâce à quoi SQL peut tirer parti de sa compréhension de la sémantique du prédicat LIKE pour peut-être utiliser un index pour l'aider à tester uniquement un ensemble réduit de correspondances possibles.

Comme suggéré dans le commentaire sous la question elle-même, n index de texte intégral sera beaucoup plus rapide. La différence dépend de la distribution spécifique des mots dans le texte, ainsi que de la taille globale du tableau, etc., mais attendez-vous à tout de deux fois plus vite à peut-être 10 fois plus vite.

Un inconvénient possible de l'utilisation de l'index de texte intégral, en plus des frais généraux pour la création d'un tel index, est que, sauf si l'on est très prudent dans la configuration de cet index (ex: définir la liste de mots vides, utiliser une syntaxe de recherche spécifique pour éviter les formes flexionnelles et similaires ...), il peut y avoir des cas où les résultats fournis par FullText ne seront pas comme prév. Par exemple, en recherchant un "SAW" (un outil pour couper du bois), on peut obtenir beaucoup de résultats pour les enregistrements, y compris le verbe "voir", dans ses diverses formes conjuguées.
Bien entendu, ces caractéristiques linguistiques des index de texte intégral peuvent généralement être ignorées et on peut également considérer que ces fonctionnalités sont effectivement un avantage, et non un inconvénient. Je mentionne cela ici car nous comparons cela à une simple recherche générique.

11
mjv

Il y a peu à ajouter au test de Razzed. Mais apparemment, l'utilisation de regexp entraîne une charge de traitement beaucoup plus lourde, contrairement à ce que Seth souligne dans son commentaire .

Les tests suivants supposent que vous définissez query_caching à On dans my.ini

query_cache_type = 1
query_cache_size = 64M

Tests

  • Les timings montrent les performances moyennes, sur trois mesures (avec le cache vidé par intermittence):

  • [~ # ~] comme [~ # ~]

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

    Initial: 0,0035 s
    En cache: 0,0005s

  • [~ # ~] expression régulière [~ # ~]

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

    Initial: 0,01 s
    En cache: 0,0004s

Résultat

LIKE ou INSTR est nettement plus rapide que REGEXP.

Bien que minime, la différence de synchronisation du cache est probablement suffisante pour justifier une enquête plus approfondie.

Sur un système MySQL probablement configuré, l'indexation plein texte devrait généralement être toujours plus rapide ou au moins comparable à une recherche non indexée. Utilisez donc l'indexation, en particulier sur les longs textes en langage humain, quel que soit le code de balisage intermittent.

3
Lorenz Lo Sauer