jsonb
trong Postgres 9.4+
Với kiểu dữ liệu JSON nhị phân mới jsonb
, Postgres 9.4 đã giới thiệu các tùy chọn chỉ mục được cải thiện đáng kể . Bây giờ bạn có thể có chỉ mục GIN trên một jsonb
mảng trực tiếp:
CREATE TABLE tracks (id serial, artists jsonb);
CREATE INDEX tracks_artists_gin_idx ON tracks USING gin (artists);
Không cần hàm để chuyển đổi mảng. Điều này sẽ hỗ trợ một truy vấn:
SELECT * FROM tracks WHERE artists @> '[{"name": "The Dirty Heads"}]';
@>
là jsonb
toán tử "chứa" mới , có thể sử dụng chỉ mục GIN. (Không dành cho loại json
, chỉjsonb
!)
Hoặc bạn sử dụng lớp toán tử GIN chuyên biệt hơn, không mặc định jsonb_path_ops
cho chỉ mục:
CREATE INDEX tracks_artists_gin_idx ON tracks
USING gin (artists jsonb_path_ops);
Cùng một truy vấn.
Hiện tại jsonb_path_ops
chỉ hỗ trợ @>
nhà mạng. Nhưng nó thường nhỏ hơn và nhanh hơn nhiều. Có thêm tùy chọn chỉ mục, chi tiết trong sách hướng dẫn .
Nếu artists
chỉ giữ các tên như được hiển thị trong ví dụ, sẽ hiệu quả hơn khi lưu trữ giá trị JSON ít dư thừa hơn để bắt đầu bằng: chỉ các giá trị dưới dạng văn bản gốc và khóa dự phòng có thể nằm trong tên cột.
Lưu ý sự khác biệt giữa các đối tượng JSON và các kiểu nguyên thủy:
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);
Truy vấn:
SELECT * FROM tracks WHERE artistnames ? 'The Dirty Heads';
?
không hoạt động cho các giá trị đối tượng , chỉ là các khóa và các phần tử mảng .
Hoặc (hiệu quả hơn nếu tên được lặp lại thường xuyên):
CREATE INDEX tracks_artistnames_gin_idx ON tracks
USING gin (artistnames jsonb_path_ops);
Truy vấn:
SELECT * FROM tracks WHERE artistnames @> '"The Dirty Heads"'::jsonb;
json
trong Postgres 9.3+
Điều này sẽ hoạt động với một IMMUTABLE
chức năng :
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)';
Tạo chỉ mục chức năng này :
CREATE INDEX tracks_artists_gin_idx ON tracks
USING gin (json2arr(artists, 'name'));
Và sử dụng một truy vấn như thế này. Biểu thức trong WHERE
mệnh đề phải khớp với biểu thức trong chỉ mục:
SELECT * FROM tracks
WHERE '{"The Dirty Heads"}'::text[] <@ (json2arr(artists, 'name'));
Cập nhật thông tin phản hồi trong nhận xét. Chúng ta cần sử dụng toán tử mảng để hỗ trợ chỉ mục GIN.
Các "được chứa bởi" nhà điều hành<@
trong trường hợp này.
Ghi chú về sự biến động của chức năng
Bạn có thể khai báo chức năng của mình IMMUTABLE
ngay cả khi json_array_elements()
không có.
Hầu hết các JSON
chức năng được sử dụng để duy nhất STABLE
, không IMMUTABLE
. Đã có một cuộc thảo luận về danh sách tin tặc để thay đổi điều đó. Hầu hết là IMMUTABLE
bây giờ. Kiểm tra với:
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%';
Chỉ mục chức năng chỉ hoạt động với các IMMUTABLE
chức năng.