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

Oprettelse af store og små bogstaver i indekser på Postgres string array

@Saurabh Nanda:I lighed med det du postede, kan du også oprette en simpel funktion til at konvertere dit varchar-array til små bogstaver som følger:

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;

Bemærk, at jeg også trimmer tags af mellemrum. Dette er måske ikke nødvendigt for dig, men jeg gør det normalt for at opnå konsistens.

Test:

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

Som bemærket af Saurabh, kan du derefter oprette et GIN-indeks:

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

Og spørg:

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

OPDATERING: Ydeevne for WHILE vs array_agg/unnest

Jeg oprettede tabel med 100K 10 element text[] arrays (12 tegn tilfældige strenge med blandede store og små bogstaver) og testede hver funktion.

Funktionen array_agg/unnest returnerede:

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 returnerede:

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)

OPDATERING 2: FOREACH vs. WHILE Som et sidste eksperiment ændrede jeg WHILE-funktionen til at bruge 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'

Resultaterne så ud til at ligne 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)

Selvom mine test på ingen måde er strenge, kørte jeg hver version et antal gange og fandt, at tallene var repræsentative, hvilket tyder på, at SQL-metoden (array_agg/unnest) er den hurtigste.



  1. WHERE datetime ældre end nogen tid (f.eks. 15 minutter)

  2. Deaktiver DELETE på bordet i PostgreSQL?

  3. Hvorfor virker denne MySQL-opdatering ikke?

  4. Hvordan sammenligner man bedst med 0 i PHP?