sql >> Database >  >> RDS >> PostgreSQL

Optimalisatie van een postgres-gelijkenisquery (pg_trgm + gin-index)

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() ?

2.

Gebruik een juiste 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:




  1. Aangepaste MySQL-kolomindeling afdwingen?

  2. Hoe u een gebruiksvriendelijke database voor uw bedrijf kiest

  3. recursieve functie voor dynamisch menu met meerdere niveaus php

  4. FOUT:functies in index-expressie moeten worden gemarkeerd als IMMUTABLE in Postgres