Ik verwacht veel snellere resultaten met deze aanpak:
1.
Maak een GiST-index met 1 kolom met aaneengeschakelde waarden:
CREATE INDEX users_search_idx ON auth_user
USING gist((username || ' ' || first_name || ' ' || last_name) gist_trgm_ops);
Dit veronderstelt dat alle 3 kolommen gedefinieerd zijn NOT NULL
(u hebt niet aangegeven). Anders moet u meer doen.
Waarom niet vereenvoudigen met concat_ws()
?
- Combineer twee kolommen en voeg toe aan één nieuwe kolom
- Sneller zoeken met patroonovereenkomst op meerdere tekstvelden
- Combineer twee kolommen en voeg toe aan één nieuwe kolom
2.
Gebruik een juiste nearest-neighbor zoekopdracht, overeenkomend met bovenstaande 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;
Uitdrukkingen in WHERE
en ORDER BY
moet overeenkomen met indexuitdrukking!
In het bijzonder ORDER BY rank
(zoals je het had) zal altijd slecht presteren voor een kleine LIMIT
kiezen uit een veel grotere pool van kwalificerende rijen, omdat het niet rechtstreeks een index kan gebruiken:de geavanceerde uitdrukking achter rank
moet worden berekend voor elke kwalificatierij, dan moeten ze allemaal worden gesorteerd voordat de kleine selectie van beste wedstrijden kan worden geretourneerd. Dit is veel, veel duurder dan een echte naaste-buur-query die de beste resultaten rechtstreeks uit de index kan halen zonder zelfs maar naar de rest te kijken.
row_number()
met lege vensterdefinitie geeft alleen de volgorde weer die is geproduceerd door de ORDER BY
van dezelfde SELECT
.
Gerelateerde antwoorden:
Wat betreft uw item 3.
, Ik heb een antwoord toegevoegd aan de vraag waarnaar u verwijst, dat zou het moeten verklaren: