jsonb
di Postgres 9.4+
Tipe data JSON biner jsonb
sebagian besar meningkatkan opsi indeks. Anda sekarang dapat memiliki indeks GIN di jsonb
array secara langsung:
CREATE TABLE tracks (id serial, artists jsonb); -- !
CREATE INDEX tracks_artists_gin_idx ON tracks USING gin (artists);
Tidak perlu fungsi untuk mengonversi array. Ini akan mendukung kueri:
SELECT * FROM tracks WHERE artists @> '[{"name": "The Dirty Heads"}]';
@>
menjadi jsonb
operator "berisi", yang dapat menggunakan indeks GIN. (Bukan untuk json
, hanya jsonb
!)
Atau Anda menggunakan kelas operator GIN non-default yang lebih khusus jsonb_path_ops
untuk indeks:
CREATE INDEX tracks_artists_gin_idx ON tracks
USING gin (artists jsonb_path_ops); -- !
Kueri yang sama.
Saat ini jsonb_path_ops
hanya mendukung @>
operator. Tapi biasanya jauh lebih kecil dan lebih cepat. Ada lebih banyak opsi indeks, detail dalam manual .
Jika kolom artists
hanya menyimpan nama seperti yang ditampilkan dalam contoh, akan lebih efisien jika hanya menyimpan nilai sebagai teks JSON primitif dan kunci red yang berlebihan bisa menjadi nama kolom.
Perhatikan perbedaan antara objek JSON dan tipe primitif:
- Menggunakan indeks dalam array json di 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);
Pertanyaan:
SELECT * FROM tracks WHERE artistnames ? 'The Dirty Heads';
?
tidak bekerja untuk objek nilai , cukup kunci dan elemen larik .
Atau:
CREATE INDEX tracks_artistnames_gin_idx ON tracks
USING gin (artistnames jsonb_path_ops);
Pertanyaan:
SELECT * FROM tracks WHERE artistnames @> '"The Dirty Heads"'::jsonb;
Lebih efisien jika nama sangat duplikasi.
json
di Postgres 9.3+
Ini harus bekerja dengan IMMUTABLE
fungsi :
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)';
Buat indeks fungsional ini :
CREATE INDEX tracks_artists_gin_idx ON tracks
USING gin (json2arr(artists, 'name'));
Dan gunakan kueri seperti ini. Ekspresi dalam WHERE
klausa harus cocok dengan yang ada di indeks:
SELECT * FROM tracks
WHERE '{"The Dirty Heads"}'::text[] <@ (json2arr(artists, 'name'));
Diperbarui dengan umpan balik dalam komentar. Kita perlu menggunakan operator array untuk mendukung indeks GIN.
Operator "diisi oleh" <@
dalam hal ini.
Catatan tentang volatilitas fungsi
Anda dapat mendeklarasikan fungsi Anda IMMUTABLE
bahkan jika json_array_elements()
bukan tidak.
Sebagian besar JSON
fungsi yang dulunya hanya STABLE
, bukan IMMUTABLE
. Ada diskusi di daftar peretas untuk mengubahnya. Sebagian besar IMMUTABLE
sekarang. Periksa dengan:
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%';
Indeks fungsional hanya berfungsi dengan IMMUTABLE
fungsi.