jsonb
v Postgres 9.4+
Binární datový typ JSON jsonb
do značné míry zlepšuje možnosti indexu. Nyní můžete mít index GIN na jsonb
pole přímo:
CREATE TABLE tracks (id serial, artists jsonb); -- !
CREATE INDEX tracks_artists_gin_idx ON tracks USING gin (artists);
Není potřeba funkce pro převod pole. To by podporovalo dotaz:
SELECT * FROM tracks WHERE artists @> '[{"name": "The Dirty Heads"}]';
@>
je jsonb
operátor "obsahuje", který může používat index GIN. (Ne pro json
, pouze jsonb
!)
Nebo používáte specializovanější, nevýchozí třídu operátorů GIN jsonb_path_ops
pro index:
CREATE INDEX tracks_artists_gin_idx ON tracks
USING gin (artists jsonb_path_ops); -- !
Stejný dotaz.
Aktuálně jsonb_path_ops
podporuje pouze @>
operátor. Ale obvykle je mnohem menší a rychlejší. Existuje více možností indexu, podrobnosti v příručce .
Pokud sloupec artists
obsahuje pouze názvy zobrazené v příkladu, bylo by efektivnější ukládat pouze hodnoty jako primitiva textu JSON a redundantní klíč může být název sloupce.
Všimněte si rozdílu mezi objekty JSON a primitivními typy:
- Použití indexů v poli json v 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);
Dotaz:
SELECT * FROM tracks WHERE artistnames ? 'The Dirty Heads';
?
nefunguje pro objektové hodnoty , stačí klávesy a prvky pole .
Nebo:
CREATE INDEX tracks_artistnames_gin_idx ON tracks
USING gin (artistnames jsonb_path_ops);
Dotaz:
SELECT * FROM tracks WHERE artistnames @> '"The Dirty Heads"'::jsonb;
Efektivnější, pokud jsou názvy vysoce duplicitní.
json
v Postgres 9.3+
To by mělo fungovat s IMMUTABLE
funkce :
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)';
Vytvořte tento funkční index :
CREATE INDEX tracks_artists_gin_idx ON tracks
USING gin (json2arr(artists, 'name'));
A použijte dotaz takhle. Výraz v WHERE
klauzule se musí shodovat s klauzulí v indexu:
SELECT * FROM tracks
WHERE '{"The Dirty Heads"}'::text[] <@ (json2arr(artists, 'name'));
Aktualizováno o zpětnou vazbu v komentářích. Musíme použít operátory pole pro podporu indexu GIN.
Operátor "je obsažen v" <@
v tomto případě.
Poznámky k volatilitě funkcí
Svou funkci můžete prohlásit za IMMUTABLE
i když json_array_elements()
není nebyl.
Většina JSON
funkce byly dříve pouze STABLE
, nikoli IMMUTABLE
. Na seznamu hackerů proběhla diskuse, která to měla změnit. Většina z nich je IMMUTABLE
Nyní. Zkontrolujte pomocí:
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%';
Funkční indexy fungují pouze s IMMUTABLE
funkce.