J'attends beaucoup des résultats plus rapides avec cette approche :
1.
Créez un index GiST avec 1 colonne contenant des valeurs concaténées :
CREATE INDEX users_search_idx ON auth_user
USING gist((username || ' ' || first_name || ' ' || last_name) gist_trgm_ops);
Cela suppose que les 3 colonnes sont définies NOT NULL
(vous n'avez pas précisé). Sinon, vous devez en faire plus.
Pourquoi ne pas simplifier avec concat_ws()
?
- Combinez deux colonnes et ajoutez-les dans une nouvelle colonne
- Requête plus rapide avec correspondance de modèles sur plusieurs champs de texte
- Combinez deux colonnes et ajoutez-les dans une nouvelle colonne
2.
Utilisez un plus proche-voisin requête, correspondant au-dessus de l'index :
SELECT username, email, first_name, last_name
, similarity(username , $1) AS s_username
, similarity(first_name, $1) AS s_first_name
, similarity(last_name , $1) AS s_last_name
, row_number() OVER () AS rank -- greatest similarity first
FROM auth_user
WHERE (username || ' ' || first_name || ' ' || last_name) % $1 -- !!
ORDER BY (username || ' ' || first_name || ' ' || last_name) <-> $1 -- !!
LIMIT $2;
Expressions dans WHERE
et ORDER BY
doit correspondre à l'expression d'index !
En particulier ORDER BY rank
(comme vous l'aviez) fonctionnera toujours mal pour un petit LIMIT
choisir parmi un pool beaucoup plus grand de lignes qualifiantes, car il ne peut pas utiliser directement un index :l'expression sophistiquée derrière rank
doit être calculé pour chaque ligne de qualification, alors tous doivent être triés avant que la petite sélection des meilleures correspondances puisse être renvoyée. C'est beaucoup, beaucoup plus cher qu'une véritable requête du plus proche voisin qui peut sélectionner directement les meilleurs résultats de l'index sans même regarder le reste.
row_number()
avec une définition de fenêtre vide reflète simplement l'ordre produit par le ORDER BY
du même SELECT
.
Réponses associées :
Quant à votre article 3.
, j'ai ajouté une réponse à la question que vous avez référencée, qui devrait l'expliquer :