sql >> Database teknologi >  >> RDS >> PostgreSQL

Optimering af en postgres-lighedsforespørgsel (pg_trgm + gin-indeks)

Jeg forventer meget hurtigere resultater med denne tilgang:

1.

Opret et GiST-indeks med 1 kolonne med sammenkædede værdier:

CREATE INDEX users_search_idx ON auth_user
USING gist((username || ' ' || first_name || ' ' || last_name) gist_trgm_ops);

Dette antager, at alle 3 kolonner er defineret NOT NULL (du har ikke angivet). Ellers skal du gøre mere.
Hvorfor ikke forenkle med concat_ws() ?

2.

Brug en ordentlig forespørgsel, der matcher ovenstående indeks:

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;

Udtryk i WHERE og ORDER BY skal matche indeksudtryk!

Især ORDER BY rank (som du havde det) vil altid fungere dårligt for en lille LIMIT at vælge fra en meget større pulje af kvalificerende rækker, fordi den ikke kan bruge et indeks direkte:Det sofistikerede udtryk bag rank skal beregnes for hver kvalificerende række, så skal alle sorteres, før det lille udvalg af bedste kampe kan returneres. Dette er meget, meget dyrere end en ægte nærmeste-nabo-forespørgsel, der kan vælge de bedste resultater fra indekset direkte uden selv at se på resten.

row_number() med tomt vindues definition afspejler bare rækkefølgen produceret af ORDER BY af den samme SELECT .

Relaterede svar:

Med hensyn til din vare 3. , jeg tilføjede et svar på det spørgsmål, du refererede til, som burde forklare det:




  1. Sådan ændres datatypen i Oracle med eksisterende rækker i tabellen

  2. Sådan forbinder du Jboss-as-7.1.1 med Postgresql

  3. Postgresql:Scripting af psql-udførelse med adgangskode

  4. MySQL GROUP_CONCAT:Formatering af output