Espero mucho resultados más rápidos con este enfoque:
1.
Cree un índice GiST con 1 columna que contenga valores concatenados:
CREATE INDEX users_search_idx ON auth_user
USING gist((username || ' ' || first_name || ' ' || last_name) gist_trgm_ops);
Esto supone que se definirán las 3 columnas NOT NULL
(no especificaste). De lo contrario, debe hacer más.
¿Por qué no simplificar con concat_ws()
? ?
- Combine dos columnas y agréguelas a una nueva columna
- Consulta más rápida con coincidencia de patrones en varios campos de texto
- Combine dos columnas y agréguelas a una nueva columna
2.
Utilice un más cercano-vecino adecuado. consulta, coincidiendo con el índice anterior:
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;
Expresiones en WHERE
y ORDER BY
¡debe coincidir con la expresión del índice!
En particular ORDER BY rank
(como si lo tuviera) siempre funcionará mal por un pequeño LIMIT
seleccionando de un grupo mucho más grande de filas calificadas, porque no puede usar un índice directamente:la expresión sofisticada detrás de rank
debe calcularse para cada fila de calificación, entonces todos deben ordenarse antes de que se pueda devolver la pequeña selección de las mejores coincidencias. Esto es mucho, mucho más caro que una verdadera consulta de vecino más cercano que puede seleccionar los mejores resultados del índice directamente sin siquiera mirar el resto.
row_number()
con una definición de ventana vacía solo refleja el orden producido por ORDER BY
del mismo SELECT
.
Respuestas relacionadas:
En cuanto a su artículo 3.
, agregué una respuesta a la pregunta a la que hizo referencia, eso debería explicarlo: