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.