क्वेरी
आपकी तालिका परिभाषा गुम है। मान लें:
CREATE TABLE configuration (
config_id serial PRIMARY KEY
, config jsonb NOT NULL
);
एक value
खोजने के लिए और दिए गए oid
. के लिए इसकी पंक्ति और 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'
यह एक निहित LATERAL
है जोड़ना। तुलना करें:
- JSON प्रकार के अंदर सरणी तत्वों के लिए क्वेरी
2) oid
. के 3 कॉलम वाली तालिका प्राप्त करने का सबसे तेज़ तरीका क्या है? , instance
और value.
मुझे लगता है कि jsonb_populate_recordset()
. का उपयोग करना चाहिए , तो आप तालिका परिभाषा में डेटा प्रकार प्रदान कर सकते हैं। मान लें कि text
सभी के लिए:
CREATE TEMP TABLE data_pattern (oid text, value text, instance text);
एक स्थायी (गैर-अस्थायी) तालिका भी हो सकती है। यह केवल वर्तमान सत्र के लिए है। फिर:
SELECT c.config_id, d.*
FROM configuration c
, jsonb_populate_recordset(NULL::data_pattern, c.config->'data') d
बस इतना ही। पहली क्वेरी फिर से लिखी गई:
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';
लेकिन यह धीमा है पहली क्वेरी की तुलना में। बड़ी तालिका के साथ प्रदर्शन की कुंजी अनुक्रमणिका समर्थन है:
सूचकांक
आप सामान्यीकृत (अनुवादित) तालिका या प्रश्न में प्रस्तावित वैकल्पिक लेआउट को आसानी से अनुक्रमित कर सकते हैं। अपने वर्तमान लेआउट को अनुक्रमित करना उतना स्पष्ट नहीं है, लेकिन संभव भी है। सर्वोत्तम प्रदर्शन के लिए मैं केवल data
. पर एक कार्यात्मक अनुक्रमणिका का सुझाव देता हूं कुंजी के साथ jsonb_path_ops
ऑपरेटर वर्ग। प्रति दस्तावेज़:
jsonb_ops
. के बीच तकनीकी अंतर और एक jsonb_path_ops
GINindex यह है कि पूर्व डेटा में प्रत्येक कुंजी और मान के लिए स्वतंत्र अनुक्रमणिका आइटम बनाता है, जबकि बाद वाला डेटा में केवल foreach मान के लिए अनुक्रमणिका आइटम बनाता है।
यह अद्भुत काम करना चाहिए प्रदर्शन के लिए:
CREATE INDEX configuration_my_idx ON configuration
USING gin ((config->'data') jsonb_path_ops);
कोई उम्मीद कर सकता है कि JSON सरणी तत्व के लिए केवल एक पूर्ण मिलान ही काम करेगा, जैसे:
SELECT * FROM configuration
WHERE (config->'data') @> '[{"oid": "1.3.6.1.4.1.7352.3.10.2.5.35.3"
, "instance": "0", "value": "1234"}]';
<उप>JSON सरणी संकेतन नोट करें (संलग्न []
. के साथ) ) प्रदान किए गए मान का, जो आवश्यक है।
लेकिन कुंजी के सबसेट with के साथ सरणी तत्व साथ ही काम करें:
SELECT * FROM configuration
WHERE (config->'data') @> '[{"oid": "1.3.6.1.4.1.7352.3.10.2.5.35.3"
, "instance": "0"}]'
कठिन हिस्सा आपके प्रतीत होने वाले संदिग्ध जोड़े गए विधेय value <> '1'
को शामिल करना है . सभी विधेय समान . पर लागू करने के लिए सावधानी बरती जानी चाहिए सरणी तत्व। आप इसे पहली क्वेरी के साथ जोड़ सकते हैं:
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
वोइला।
विशेष अनुक्रमणिका
यदि आपकी तालिका विशाल है, तो सूचकांक का आकार एक निर्णायक कारक हो सकता है। आप एक कार्यात्मक सूचकांक के साथ इस विशेष समाधान के प्रदर्शन की तुलना कर सकते हैं:
यह फ़ंक्शन oid-instance . की एक पोस्टग्रेस सरणी निकालता है किसी दिए गए jsonb
. से संयोजन मूल्य:
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$
हम इसके आधार पर एक कार्यात्मक सूचकांक बना सकते हैं:
CREATE INDEX configuration_conrfig_special_idx ON configuration
USING gin (f_config_json2arr(config->'data'));
और इसके आधार पर प्रश्न पूछें:
SELECT * FROM configuration
WHERE f_config_json2arr(config->'data') @> '{1.3.6.1.4.1.7352.3.10.2.5.35.3-0}'::text[]
विचार यह है कि सूचकांक काफी छोटा होना चाहिए क्योंकि यह बिना चाबियों के केवल संयुक्त मूल्यों को संग्रहीत करता है। सरणी नियंत्रण ऑपरेटर @>
खुद को jsonb कंटेन्मेंट ऑपरेटर के समान प्रदर्शन करना चाहिए @>
. मुझे बड़े अंतर की उम्मीद नहीं है, लेकिन मुझे बहुत दिलचस्पी होगी जो तेज़ है।
इस संबंधित उत्तर में पहले समाधान के समान (लेकिन अधिक विशिष्ट):
- JSON सरणी में किसी तत्व को खोजने के लिए अनुक्रमणिका
एसाइड्स:
- मैं
oid
का उपयोग नहीं करूंगा कॉलम नाम के रूप में क्योंकि इसका उपयोग पोस्टग्रेज़ में आंतरिक उद्देश्यों के लिए भी किया जाता है। - यदि संभव हो, तो मैं JSON के बिना एक सादा, सामान्यीकृत तालिका का उपयोग करूंगा।