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

Comment indexer une table postgres par nom, quand le nom peut être dans n'importe quelle langue ?

Si vous souhaitez optimiser les correspondances de sous-chaînes arbitraires, une option consiste à utiliser le pg_tgrm modules . Ajouter un index :

CREATE INDEX table_location_name_trigrams_key ON table
  USING gin (location_name gin_trgm_ops);

Cela décomposera "Simple Cafe" en "sim", "imp", "mpl", etc., et ajoutera une entrée à l'index pour chaque trigam dans chaque ligne. Le planificateur de requêtes peut alors utiliser automatiquement cet index pour les correspondances de modèles de sous-chaînes, notamment :

SELECT * FROM table WHERE location_name ILIKE '%cafe%';

Cette requête recherchera "caf" et "afe" dans l'index, trouvera l'intersection, récupérera ces lignes, puis vérifiera chaque ligne par rapport à votre modèle. (Cette dernière vérification est nécessaire car l'intersection de "caf" et "afe" correspond à la fois à "café simple" et à "échafaudage dangereux", tandis que "%cafe%" ne doit correspondre qu'à un seul). L'index devient plus efficace à mesure que le modèle d'entrée s'allonge car il peut exclure plus de lignes, mais il n'est toujours pas aussi efficace que l'indexation de mots entiers, alors ne vous attendez pas à une amélioration des performances par rapport à to_tsvector .

Le hic, c'est que les trigrammes ne fonctionnent pas du tout pour les motifs de moins de trois caractères. Cela peut ou non être un facteur décisif pour votre application.

Modifier : J'ai d'abord ajouté ceci en tant que commentaire.

J'ai eu une autre pensée la nuit dernière alors que je dormais presque. Faire un cjk_chars fonction qui prend une chaîne d'entrée, regexp_matches l'ensemble des plages CJK Unicode et renvoie un tableau de ces caractères ou NULL si aucun. Ajouter un index GIN sur cjk_chars(location_name) . Ensuite, recherchez :

WHERE CASE
  WHEN cjk_chars('query') IS NOT NULL THEN
    cjk_chars(location_name) @> cjk_chars('query')
    AND location_name LIKE '%query%'
  ELSE
    <tsvector/trigrams>
  END

Ta-da, unigrammes !