sql >> Databáze >  >> RDS >> PostgreSQL

Jak indexovat tabulku postgres podle názvu, když název může být v libovolném jazyce?

Pokud chcete optimalizovat libovolné shody podřetězců, jednou z možností je použít kód pg_tgrm modul . Přidat index:

CREATE INDEX table_location_name_trigrams_key ON table
  USING gin (location_name gin_trgm_ops);

To rozdělí "Simple Cafe" na "sim", "imp", "mpl" atd. a přidá záznam do indexu pro každý trigam v každém řádku. Plánovač dotazů pak může tento index automaticky použít pro shody vzorů podřetězců, včetně:

SELECT * FROM table WHERE location_name ILIKE '%cafe%';

Tento dotaz vyhledá „caf“ a „afe“ v indexu, najde průsečík, načte tyto řádky a poté každý řádek porovná s vaším vzorem. (Tato poslední kontrola je nezbytná, protože průsečík "caf" a "afe" odpovídá jak "jednoduchá kavárna" tak "nebezpečné lešení", zatímco "%cafe%" by mělo odpovídat pouze jednomu). Index se stává efektivnější, když se vstupní vzor prodlužuje, protože může vyloučit více řádků, ale stále není tak účinný jako indexování celých slov, takže neočekávejte zlepšení výkonu oproti to_tsvector .

Háček je v tom, že trigramy nefungují vůbec pro vzory, které mají méně než tři znaky. To může, ale nemusí být pro vaši aplikaci překážkou.

Upravit: Původně jsem to přidal jako komentář.

Včera v noci, když jsem většinou spal, mě napadla jiná myšlenka. Vytvořte cjk_chars funkce, která přebírá vstupní řetězec, regexp_matches celý rozsah CJK Unicode a vrátí pole jakýchkoli takových znaků nebo NULL pokud žádný. Přidejte index GIN na cjk_chars(location_name) . Poté dotaz na:

WHERE CASE
  WHEN cjk_chars('query') IS NOT NULL THEN
    cjk_chars(location_name) @> cjk_chars('query')
    AND location_name LIKE '%query%'
  ELSE
    <tsvector/trigrams>
  END

Ta-da, unigramy!



  1. Jak zachytit a analyzovat události SQL Server

  2. Jaký je výkon mysql BETWEEN přes...?

  3. Průvodce návrhem databáze pro události kalendáře a připomenutí v MySQL

  4. Jak přidám cluster na složený klíč?