PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

Mảng Postgres 9.4 jsonb dưới dạng bảng

Truy vấn

Định nghĩa bảng của bạn bị thiếu. Giả sử:

CREATE TABLE configuration (
  config_id serial PRIMARY KEY
, config jsonb NOT NULL
);

Để tìm giá trị value và hàng của nó cho oid đã cho và instance :

SELECT c.config_id, d->>'value' AS value
FROM   configuration c
     , jsonb_array_elements(config->'data') d  -- default col name is "value"
WHERE  d->>'oid'      = '1.3.6.1.4.1.7352.3.10.2.5.35.3'
AND    d->>'instance' = '0'
AND    d->>'value'   <> '1'

Đó là một LATERAL ngầm hiểu tham gia. So sánh:

  • Truy vấn các phần tử mảng bên trong kiểu JSON

2) Cách nhanh nhất để lấy bảng có 3 cột oid là gì , instance và giá trị value.

Tôi cho rằng sử dụng jsonb_populate_recordset() , thì bạn có thể cung cấp các kiểu dữ liệu trong định nghĩa bảng. Giả sử text cho tất cả:

CREATE TEMP TABLE data_pattern (oid text, value text, instance text);

Cũng có thể là một bảng lâu dài (không tạm thời). Cái này chỉ dành cho phiên hiện tại. Sau đó:

SELECT c.config_id, d.*
FROM   configuration c
     , jsonb_populate_recordset(NULL::data_pattern, c.config->'data') d

Đó là tất cả. Truy vấn đầu tiên được viết lại:

SELECT c.config_id, d.*
FROM   configuration c
     , jsonb_populate_recordset(NULL::data_pattern, c.config->'data') d
WHERE  d.oid      = '1.3.6.1.4.1.7352.3.10.2.5.35.3'
AND    d.instance = '0'
AND    d.value   <> '1';

Nhưng điều đó chậm hơn so với truy vấn đầu tiên. Chìa khóa để đạt được hiệu suất với bảng lớn hơn là hỗ trợ chỉ mục:

Chỉ mục

Bạn có thể dễ dàng lập chỉ mục bảng chuẩn hóa (đã dịch) hoặc bố cục thay thế mà bạn đã đề xuất trong câu hỏi. Lập chỉ mục bố cục hiện tại của bạn là không rõ ràng, nhưng cũng có thể. Để có hiệu suất tốt nhất, tôi đề xuất một chỉ mục chức năng chỉ trên data khóa bằng jsonb_path_ops lớp toán tử. Theo tài liệu:

Sự khác biệt về kỹ thuật giữa jsonb_ops và một jsonb_path_ops GINindex là cái trước tạo các mục chỉ mục độc lập cho mỗi khóa và giá trị trong dữ liệu, trong khi cái sau tạo các mục chỉ mục chỉ hiển thị giá trị trong dữ liệu.

Điều này sẽ làm nên điều kỳ diệu cho hiệu suất:

CREATE INDEX configuration_my_idx ON configuration
USING gin ((config->'data') jsonb_path_ops);

Người ta có thể mong đợi rằng chỉ có một kết hợp hoàn chỉnh cho một phần tử mảng JSON mới hoạt động, như:

SELECT * FROM configuration
WHERE  (config->'data') @> '[{"oid": "1.3.6.1.4.1.7352.3.10.2.5.35.3"
                            , "instance": "0", "value": "1234"}]';

Lưu ý ký hiệu mảng JSON (với bao gồm [] ) của giá trị đã cung cấp, đó là giá trị bắt buộc.

Nhưng các phần tử mảng có tập hợp khóa con hoạt động tốt:

SELECT * FROM configuration
WHERE  (config->'data') @> '[{"oid": "1.3.6.1.4.1.7352.3.10.2.5.35.3"
                            , "instance": "0"}]'

Phần khó là kết hợp vị từ được thêm vào có vẻ không tốt của bạn value <> '1' . Cần phải cẩn thận để áp dụng tất cả các vị từ cho cùng một phần tử mảng. Bạn có thể kết hợp điều này với truy vấn đầu tiên:

SELECT c.*, d->>'value' AS value
FROM   configuration c
     , jsonb_array_elements(config->'data') d
WHERE  (config->'data') @> '[{"oid": "1.3.6.1.4.1.7352.3.10.2.5.35.3", "instance": "0"}]'
AND    d->>'oid'      = '1.3.6.1.4.1.7352.3.10.2.5.35.3'  -- must be repeated
AND    d->>'instance' = '0'                               -- must be repeated
AND    d->>'value'   <> '1'                               -- here we can rule out

Voilá.

Chỉ mục đặc biệt

Nếu bảng của bạn lớn, kích thước chỉ mục có thể là một yếu tố quyết định. Bạn có thể so sánh hiệu suất của giải pháp đặc biệt này với một chỉ số chức năng:

Hàm này trích xuất một mảng Postgres của oid-instance kết hợp từ một jsonb nhất định giá trị:

CREATE OR REPLACE FUNCTION f_config_json2arr(_j jsonb)
  RETURNS text[] LANGUAGE sql IMMUTABLE AS
$func$
SELECT ARRAY(
   SELECT (elem->>'oid') || '-' || (elem->>'instance')
   FROM   jsonb_array_elements(_j) elem
   )
$func$

Chúng tôi có thể xây dựng một chỉ mục chức năng dựa trên điều này:

CREATE INDEX configuration_conrfig_special_idx ON configuration
USING  gin (f_config_json2arr(config->'data'));

Và dựa trên truy vấn:

SELECT * FROM configuration
WHERE  f_config_json2arr(config->'data') @> '{1.3.6.1.4.1.7352.3.10.2.5.35.3-0}'::text[]

Ý tưởng là chỉ mục nên nhỏ hơn đáng kể vì nó chỉ lưu trữ các giá trị kết hợp mà không có khóa. Mảng toán tử ngăn chặn @> chính nó sẽ hoạt động tương tự như toán tử chứa jsonb @> . Tôi không mong đợi một sự khác biệt lớn, nhưng tôi sẽ rất quan tâm đến việc nào là nhanh hơn.

Tương tự như giải pháp đầu tiên trong câu trả lời liên quan này (nhưng chuyên biệt hơn):

  • Chỉ mục để tìm một phần tử trong mảng JSON

Bên cạnh:

  • Tôi sẽ không sử dụng oid làm tên cột vì nó cũng được sử dụng cho các mục đích nội bộ trong Postgres.
  • Nếu có thể, tôi sẽ sử dụng một bảng đơn giản, chuẩn hóa không có JSON.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. fe_sendauth:không cung cấp mật khẩu

  2. ĐẶT HÀNG THEO Bí danh không hoạt động

  3. @JoinColumn là gì và nó được sử dụng như thế nào trong Hibernate

  4. Ràng buộc kiểm tra PostgreSQL cho điều kiện khóa ngoại

  5. Chọn bản ghi đầu tiên nếu không có bản ghi nào phù hợp