PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Indeks do znajdowania elementu w tablicy JSON

jsonb w Postgresie 9.4+

Binarny typ danych JSON jsonb znacznie poprawia opcje indeksowe. Możesz teraz mieć indeks GIN na jsonb tablica bezpośrednio:

CREATE TABLE tracks (id serial, artists jsonb);  -- !
CREATE INDEX tracks_artists_gin_idx ON tracks USING gin (artists);

Nie ma potrzeby używania funkcji do konwersji tablicy. To wspierałoby zapytanie:

SELECT * FROM tracks WHERE artists @> '[{"name": "The Dirty Heads"}]';

@> będąc jsonb operator "zawiera", który może używać indeksu WZ. (Nie dla json , tylko jsonb !)

Lub używasz bardziej wyspecjalizowanej, innej niż domyślna klasa operatora GIN jsonb_path_ops dla indeksu:

CREATE INDEX tracks_artists_gin_idx ON tracks
USING  gin (artists jsonb_path_ops);  -- !

To samo zapytanie.

Obecnie jsonb_path_ops obsługuje tylko @> operator. Ale zazwyczaj jest znacznie mniejszy i szybszy. Jest więcej opcji indeksowania, szczegóły w instrukcji .

Jeśli kolumna artists przechowuje tylko nazwy pokazane w przykładzie, bardziej efektywne byłoby przechowywanie tylko wartości jako tekst JSON prymitywy i zbędny klucz może być nazwą kolumny.

Zwróć uwagę na różnicę między obiektami JSON a typami pierwotnymi:

  • Korzystanie z indeksów w tablicy json w PostgreSQL
CREATE TABLE tracks (id serial, artistnames jsonb);
INSERT INTO tracks  VALUES (2, '["The Dirty Heads", "Louis Richards"]');

CREATE INDEX tracks_artistnames_gin_idx ON tracks USING gin (artistnames);

Zapytanie:

SELECT * FROM tracks WHERE artistnames ? 'The Dirty Heads';

? nie działa dla wartości obiektu , tylko klawisze i elementy tablicy .

Lub:

CREATE INDEX tracks_artistnames_gin_idx ON tracks
USING  gin (artistnames jsonb_path_ops);

Zapytanie:

SELECT * FROM tracks WHERE artistnames @> '"The Dirty Heads"'::jsonb;

Bardziej wydajne, jeśli nazwy się duplikują.

json w Postgresie 9.3+

To powinno działać z IMMUTABLE funkcja :

CREATE OR REPLACE FUNCTION json2arr(_j json, _key text)
  RETURNS text[] LANGUAGE sql IMMUTABLE AS
'SELECT ARRAY(SELECT elem->>_key FROM json_array_elements(_j) elem)';

Utwórz ten funkcjonalny indeks :

CREATE INDEX tracks_artists_gin_idx ON tracks
USING  gin (json2arr(artists, 'name'));

I użyj zapytania lubię to. Wyrażenie w WHERE klauzula musi być zgodna z tą w indeksie:

SELECT * FROM tracks
WHERE  '{"The Dirty Heads"}'::text[] <@ (json2arr(artists, 'name'));

Zaktualizowano o opinie w komentarzach. Musimy użyć operatorów tablicowych do obsługi indeksu GIN.
Operator „zawarty w” <@ w tym przypadku.

Uwagi dotyczące zmienności funkcji

Możesz zadeklarować swoją funkcję IMMUTABLE nawet jeśli json_array_elements() nie jest nie było.
Większość JSON funkcje były tylko STABLE , a nie IMMUTABLE . Na liście hakerów odbyła się dyskusja, aby to zmienić. Większość jest IMMUTABLE teraz. Skontaktuj się z:

SELECT p.proname, p.provolatile
FROM   pg_proc p
JOIN   pg_namespace n ON n.oid = p.pronamespace
WHERE  n.nspname = 'pg_catalog'
AND    p.proname ~~* '%json%';

Indeksy funkcjonalne działają tylko z IMMUTABLE funkcje.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. rozpakuj tablicę postgresql w wiersze

  2. java.math.BigInteger nie można rzutować na java.lang.Integer

  3. psql - zapisz wyniki polecenia do pliku

  4. Najważniejsze rzeczy do monitorowania w PostgreSQL — analiza obciążenia

  5. GROUP BY + CASE oświadczenie