sql >> Databasteknik >  >> RDS >> PostgreSQL

Hur indexerar man en postgres-tabell efter namn, när namnet kan vara på vilket språk som helst?

Om du vill optimera godtyckliga delsträngsmatchningar är ett alternativ att använda pg_tgrm modul . Lägg till ett index:

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

Detta kommer att dela upp "Simple Cafe" i "sim", "imp", "mpl", etc., och lägga till en post till indexet för varje trigam i varje rad. Frågeplaneraren kan sedan automatiskt använda detta index för delsträngsmönstermatchningar, inklusive:

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

Den här frågan kommer att slå upp "caf" och "afe" i indexet, hitta korsningen, hämta dessa rader och sedan kontrollera varje rad mot ditt mönster. (Den sista kontrollen är nödvändig eftersom skärningspunkten mellan "caf" och "afe" matchar både "enkelt café" och "osäkra byggnadsställningar", medan "%cafe%" bara ska matcha en). Indexet blir mer effektivt när inmatningsmönstret blir längre eftersom det kan utesluta fler rader, men det är fortfarande inte lika effektivt som att indexera hela ord, så förvänta dig inte en prestandaförbättring jämfört med to_tsvector .

Haken är att trigram inte fungerar alls för mönster som under tre tecken. Det kan eller kanske inte är en deal-breaker för din ansökan.

Redigera: Jag lade först till detta som en kommentar.

Jag fick en annan tanke igår kväll när jag mest sov. Gör en cjk_chars funktion som tar en indatasträng, regexp_matches hela CJK Unicode-intervallen och returnerar en array av sådana tecken eller NULL om ingen. Lägg till ett GIN-index på cjk_chars(location_name) . Fråga sedan efter:

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, unigram!



  1. Fel med en Symfony-fråga:förväntad bokstavlig, fick ''

  2. HighCharts-problem i dubbla axlar, linje- och kolumndiagram

  3. SQL WHERE kolumn =allt

  4. Använder grupp efter på två fält och räkna i SQL