sql >> Databasteknik >  >> RDS >> PostgreSQL

Skapa skiftlägesokänsliga index på Postgres strängarray

@Saurabh Nanda:I likhet med vad du postade kan du också skapa en enkel funktion för att konvertera din varchar-array till gemener enligt följande:

CREATE OR REPLACE FUNCTION array_lowercase(varchar[]) RETURNS varchar[] AS
$BODY$
  SELECT array_agg(q.tag) FROM (
    SELECT btrim(lower(unnest($1)))::varchar AS tag
  ) AS q;
$BODY$
  language sql IMMUTABLE;

Observera att jag också trimmar taggar för mellanslag. Detta kanske inte är nödvändigt för dig, men jag brukar göra det för konsekvens.

Testar:

SELECT array_lowercase(array['Hello','WOrLD']);
 array_lowercase 
-----------------
 {hello,world}
(1 row)

Som noterat av Saurabh kan du sedan skapa ett GIN-index:

CREATE INDEX ix_tags ON tagtable USING GIN(array_lowercase(tags));

Och fråga:

SELECT * FROM tagtable WHERE ARRAY['mytag'::varchar] && array_lowercase(tags);

UPPDATERING: Prestanda för WHILE vs array_agg/unnest

Jag skapade en tabell med 100K 10 element text[] arrays (12 tecken slumpmässiga blandade kasussträngar) och testade varje funktion.

Funktionen array_agg/unnest returnerade:

EXPLAIN ANALYZE VERBOSE SELECT array_lowercase(data) FROM test;
                                                       QUERY PLAN                                                       
------------------------------------------------------------------------------------------------------------------------
 Seq Scan on public.test  (cost=0.00..28703.00 rows=100000 width=184) (actual time=0.320..3041.292 rows=100000 loops=1)
   Output: array_lowercase((data)::character varying[])
 Total runtime: 3174.690 ms
(3 rows)

WHILE-funktionen returnerade:

EXPLAIN ANALYZE VERBOSE SELECT array_lowercase_while(data) FROM test;
                                                       QUERY PLAN                                                       
------------------------------------------------------------------------------------------------------------------------
 Seq Scan on public.test  (cost=0.00..28703.00 rows=100000 width=184) (actual time=5.128..4356.647 rows=100000 loops=1)
   Output: array_lowercase_while((data)::character varying[])
 Total runtime: 4485.226 ms
(3 rows)

UPPDATERING 2: FOREACH kontra WHILE Som ett sista experiment ändrade jag WHILE-funktionen till att använda FOREACH:

CREATE OR REPLACE FUNCTION array_lowercase_foreach(p_input varchar[]) RETURNS varchar[] AS $BODY$
DECLARE
    el text;
    r varchar[];
BEGIN
    FOREACH el IN ARRAY p_input LOOP
        r := r || btrim(lower(el))::varchar;
    END LOOP;
    RETURN r;
END;
$BODY$
  language 'plpgsql'

Resultaten verkade likna WHILE :

EXPLAIN ANALYZE VERBOSE SELECT array_lowercase_foreach(data) FROM test;
                                                       QUERY PLAN                                                       
------------------------------------------------------------------------------------------------------------------------
 Seq Scan on public.test  (cost=0.00..28703.00 rows=100000 width=184) (actual time=0.707..4106.867 rows=100000 loops=1)
   Output: array_lowercase_foreach((data)::character varying[])
 Total runtime: 4239.958 ms
(3 rows)

Även om mina tester inte på något sätt är rigorösa, körde jag varje version ett antal gånger och fann att siffrorna var representativa, vilket tyder på att SQL-metoden (array_agg/unnest) är den snabbaste.



  1. vad är skillnaden mellan '!=' och '<>' i mysql

  2. MySQL går med och COUNT(*) från en annan tabell

  3. Inaktivera viss rad i JTable med data från databasen

  4. Varför kommer NULL-värden först när man beställer DESC i en PostgreSQL-fråga?