jsonb
trong Postgres 9.4+
Kiểu dữ liệu JSON nhị phân jsonb
cải thiện phần lớn các tùy chọn chỉ mục. Bây giờ bạn có thể có chỉ mục GIN trên 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", có thể sử dụng chỉ mục GIN. (Không dành cho json
, chỉ jsonb
!)
Hoặc bạn sử dụng lớp toán tử GIN chuyên biệt hơn, không phải 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à điều hành. Nhưng nó thường nhỏ hơn và nhanh hơn nhiều. Có nhiều tùy chọn chỉ mục hơn, chi tiết trong hướng dẫn sử dụng .
Nếu cột artists
chỉ giữ các tên được hiển thị trong ví dụ, sẽ hiệu quả hơn nếu chỉ lưu trữ các giá trị dưới dạng văn bản JSON nguyên thủy và khóa dư thừa có thể là 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:
- Sử dụng các chỉ mục trong mảng json trong 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);
Truy vấn:
SELECT * FROM tracks WHERE artistnames ? 'The Dirty Heads';
?
không hoạt động cho đối tượng giá trị , chỉ phím và phần tử mảng .
Hoặc:
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;
Hiệu quả hơn nếu tên có tính trùng lặp cao.
json
trong Postgres 9.3+
Điều này sẽ hoạt động với 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 truy vấn như thế này. Biểu thức trong WHERE
mệnh đề phải khớp với mệnh đề 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 tôi cần sử dụng toán tử mảng để hỗ trợ chỉ mục GIN.
Toán tử "được chứa bởi" <@
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 hàm của mình IMMUTABLE
ngay cả khi json_array_elements()
không phải không.
Hầu hết JSON
các chức năng được sử dụng để chỉ STABLE
, không phải 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
Hiện nay. 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 IMMUTABLE
các chức năng.