it-swarm-eu.dev

Jak vytvořit index k urychlení agregovaného dotazu LIKE na výraz?

Možná se ptám na špatnou otázku v názvu. Zde jsou fakta:

Můj zákaznický servis se stěžoval na pomalé doby odezvy při vyhledávání zákazníků v administračním rozhraní našeho webu založeného na Djangu.

Používáme Postgres 8.4.6. Začal jsem zaznamenávat pomalé dotazy a objevil jsem tohoto viníka:

SELECT COUNT(*) FROM "auth_user" WHERE UPPER("auth_user"."email"::text) LIKE UPPER(E'%deyk%')

Spuštění tohoto dotazu trvá 32 sekund. Zde je plán dotazů poskytovaný EXPLAINEM:

QUERY PLAN
Aggregate  (cost=205171.71..205171.72 rows=1 width=0)
  ->  Seq Scan on auth_user  (cost=0.00..205166.46 rows=2096 width=0)
        Filter: (upper((email)::text) ~~ '%DEYK%'::text)

Protože se jedná o dotaz generovaný pomocí Django ORM z a Django QuerySet generovaného pomocí Django administrátorské aplikace), nemám Nemám žádnou kontrolu nad samotným dotazem. Index vypadá jako logické řešení. Snažil jsem se vytvořit index, aby se to urychlilo, ale to nijak nezměnilo:

CREATE INDEX auth_user_email_upper ON auth_user USING btree (upper(email::text))

Co dělám špatně? Jak mohu tento dotaz urychlit?

22
David Eyk

Neexistuje podpora indexů pro LIKE/ILIKE in PostgreSQL 8.4 - s výjimkou vlevo ukotvené vyhledávání) podmínky .

Protože PostgreSQL 9.1 další modul pg_trgm poskytuje třídy operátorů pro indexy GIN a Gist trigramy podporující LIKE/ILIKE nebo regulární výrazy (operátory ~ a přátelé). Nainstalovat jednou do databáze:

CREATE EXTENSION pg_trgm;

Příklad indexu GIN:

CREATE INDEX tbl_col_gin_trgm_idx ON tbl USING gin (col gin_trgm_ops);

Příbuzný:

24

Tento index nepomůže, protože '%' na začátku zápasu - index BTREE může odpovídat pouze předponám a zástupný znak na začátku dotazu znamená, že neexistuje žádná pevná předpona, která by se měla hledat.

To je důvod, proč provádí skenování tabulky a porovnává každý záznam podle pořadí s řetězcem dotazu.

Pravděpodobně byste se měli podívat na použití fulltextového indexu a operátorů na porovnávání textu, spíše než na vyhledávání podřetězců pomocí LIKE, že jste v tuto chvíli. Více o fulltextovém vyhledávání najdete v dokumentaci:

http://www.postgresql.org/docs/8.4/static/textsearch-intro.html

Ve skutečnosti si z této stránky všimnu, že LIKE zjevně nikdy nepoužívá indexy, což se mi zdá divné, protože by mělo být schopno řešit předpony bez zástupných znaků pomocí indexu BTREE. Několik rychlých testů naznačuje, že dokumentace je pravděpodobně správná, v takovém případě vám však při řešení dotazu nepomůže žádné indexování, zatímco pomocí příkazu LIKE.

9
TomH