PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Erstellen von Indizes ohne Berücksichtigung der Groß-/Kleinschreibung für ein Postgres-String-Array

@Saurabh Nanda:Ähnlich wie Sie es gepostet haben, können Sie auch eine einfache Funktion erstellen, um Ihr varchar-Array wie folgt in Kleinbuchstaben umzuwandeln:

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;

Beachten Sie, dass ich auch die Tags von Leerzeichen kürze. Dies ist für Sie möglicherweise nicht erforderlich, aber ich tue es normalerweise aus Konsistenzgründen.

Testen:

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

Wie von Saurabh angemerkt, können Sie dann einen GIN-Index erstellen:

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

Und Abfrage:

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

AKTUALISIERUNG: Leistung von WHILE vs array_agg/unnest

Ich habe eine Tabelle mit 100K 10 Elementen text[] erstellt Arrays (12 Zeichen zufällig gemischte Zeichenketten) und jede Funktion getestet.

Die Funktion array_agg/unnest hat zurückgegeben:

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)

Die WHILE-Funktion hat Folgendes zurückgegeben:

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)

AKTUALISIERUNG 2: FOREACH vs. WHILE Als letztes Experiment habe ich die WHILE-Funktion so geändert, dass sie FOREACH:

verwendet
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'

Die Ergebnisse schienen denen von WHILE ähnlich zu sein :

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)

Obwohl meine Tests keineswegs streng sind, habe ich jede Version einige Male ausgeführt und festgestellt, dass die Zahlen repräsentativ sind, was darauf hindeutet, dass die SQL-Methode (array_agg/unnest) die schnellste ist.