PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Variations des performances des requêtes PostgreSQL LIKE

FTS ne prend pas en charge LIKE

La réponse précédemment acceptée était incorrecte. La recherche de texte intégral avec ses index de texte intégral n'est pas pour le LIKE opérateur du tout, il a ses propres opérateurs et ne fonctionne pas pour des chaînes arbitraires. Il fonctionne sur mots basé sur des dictionnaires et des radicaux. Ça fait prend en charge la correspondance de préfixe pour les mots , mais pas avec le LIKE opérateur :

  • Obtenir une correspondance partielle à partir de la colonne TSVECTOR indexée GIN

Indices trigrammes pour LIKE

Installez le module supplémentaire pg_trgm qui fournit des classes d'opérateurs pour les index de trigrammes GIN et GiST pour prendre en charge tous les LIKE et ILIKE motifs , pas seulement ceux ancrés à gauche :

Exemple d'index :

CREATE INDEX tbl_col_gin_trgm_idx  ON tbl USING gin  (col gin_trgm_ops);

Ou :

CREATE INDEX tbl_col_gist_trgm_idx ON tbl USING gist (col gist_trgm_ops);
  • Différence entre l'indice GiST et GIN

Exemple de requête :

SELECT * FROM tbl WHERE col LIKE '%foo%';   -- leading wildcard
SELECT * FROM tbl WHERE col ILIKE '%foo%';  -- works case insensitively as well

Trigrammes ? Qu'en est-il des chaînes plus courtes ?

Mots avec moins de 3 lettres dans les valeurs indexées fonctionnent toujours. Le manuel :

Chaque mot est considéré comme ayant deux espaces préfixés et un espace suffixé lors de la détermination de l'ensemble des trigrammes contenus dans la chaîne.

Et les modèles de recherche avec moins de 3 lettres ? Le manuel :

Pour les deux LIKE et les recherches d'expressions régulières, gardez à l'esprit qu'un modèle sans trigrammes extractibles dégénérera en un parcours d'index complet.

Cela signifie que les analyses d'index / d'index bitmap fonctionnent toujours (les plans de requête pour l'instruction préparée ne se cassent pas), cela ne vous offrira tout simplement pas de meilleures performances. Généralement pas de grosse perte, car les chaînes de 1 ou 2 lettres ne sont guère sélectives (plus de quelques pour cent des correspondances de table sous-jacentes) et la prise en charge de l'index n'améliorerait pas les performances au départ, car une analyse complète de la table est plus rapide.


text_pattern_ops pour la correspondance de préfixe

Pour juste ancré à gauche modèles (pas de caractère générique en tête), vous obtenez l'optimum avec une classe d'opérateur appropriée pour un index btree :text_pattern_ops ou varchar_pattern_ops . Les deux fonctionnalités intégrées de Postgres standard, aucun module supplémentaire n'est nécessaire. Performances similaires, mais index beaucoup plus petit.

Exemple d'index :

CREATE INDEX tbl_col_text_pattern_ops_idx ON tbl(col text_pattern_ops);

Exemple de requête :

SELECT * FROM tbl WHERE col LIKE 'foo%';  -- no leading wildcard

Ou , si vous devez exécuter votre base de données avec le 'C' locale (en fait non locale), alors tout est trié selon l'ordre des octets de toute façon et un index btree simple avec la classe d'opérateur par défaut fait le travail.

Plus de détails, d'explications, d'exemples et de liens dans ces réponses connexes sur dba.SE :

  • Mise en correspondance de modèles avec LIKE, SIMILAR TO ou des expressions régulières dans PostgreSQL
  • Comment LIKE est-il mis en œuvre ?
  • Trouver rapidement des chaînes similaires avec PostgreSQL