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.