PostgreSQL
 sql >> डेटाबेस >  >> RDS >> PostgreSQL

बिटवाइज़ और ऑपरेटर के साथ बिटस्ट्रिंग कॉलम पर बहिष्करण बाधा

जैसा कि आपके संपादन ने स्पष्ट किया, आपने एक्सटेंशन btree_gist . इसके बिना, उदाहरण पहले से ही name WITH = . पर विफल हो जाएगा ।

CREATE EXTENSION btree_gist;

btree_gist . द्वारा स्थापित ऑपरेटर कक्षाएं कई ऑपरेटरों को कवर करें। दुर्भाग्य से, & ऑपरेटर उनमें से नहीं है। जाहिर है क्योंकि यह एक बूलियन नहीं लौटाता है जो एक ऑपरेटर से अर्हता प्राप्त करने की अपेक्षा की जाएगी।

वैकल्पिक समाधान

मैं एक b-पेड़ बहु-स्तंभ अनुक्रमणिका . के संयोजन का उपयोग करूंगा (गति के लिए) और एक ट्रिगर बजाय। PostgreSQL 9.1 . पर परीक्षण किए गए इस डेमो पर विचार करें :

CREATE TABLE t (
  name text 
 ,value bit(8)
);

INSERT INTO t VALUES ('a', B'10101010'); 

CREATE INDEX t_name_value_idx ON t (name, value);

CREATE OR REPLACE FUNCTION trg_t_name_value_inversion_prohibited()
  RETURNS trigger AS
$func$
BEGIN
IF EXISTS (
     SELECT 1 FROM t
     WHERE (name, value) = (NEW.name, ~ NEW.value)  -- example: exclude inversion
     ) THEN

    RAISE EXCEPTION 'Your text here!';
END IF;

RETURN NEW;
END
$func$ LANGUAGE plpgsql;

CREATE TRIGGER insup_bef_t_name_value_inversion_prohibited
BEFORE INSERT OR UPDATE OF name, value  -- only involved columns relevant!
ON t
FOR EACH ROW
EXECUTE PROCEDURE trg_t_name_value_inversion_prohibited();

INSERT INTO t VALUES ('a', ~ B'10101010');  -- fails with your error msg.

बहिष्करण बाधा से वास्तव में बेहतर प्रदर्शन करना चाहिए, क्योंकि बी-ट्री इंडेक्स का रखरखाव जीआईएसटी इंडेक्स से सस्ता है। और बुनियादी = . के साथ लुक-अप ऑपरेटरों को & . के साथ काल्पनिक लुक-अप की तुलना में तेज़ होना चाहिए ऑपरेटर।

यह समाधान बहिष्करण बाधा जितना सुरक्षित नहीं है, क्योंकि ट्रिगर को अधिक आसानी से दरकिनार किया जा सकता है - उदाहरण के लिए उसी घटना पर बाद के ट्रिगर में, या यदि ट्रिगर अस्थायी रूप से अक्षम है। यदि ऐसी शर्तें लागू होती हैं, तो पूरी मेज पर अतिरिक्त जांच चलाने के लिए तैयार रहें।

अधिक जटिल स्थिति

उदाहरण ट्रिगर केवल value . के व्युत्क्रम को पकड़ता है . जैसा कि आपने अपनी टिप्पणी में स्पष्ट किया है, आपको वास्तव में इस तरह की स्थिति की आवश्यकता है:

IF EXISTS (
      SELECT 1 FROM t
      WHERE  name = NEW.name
      AND    value & NEW.value <> B'00000000'::bit(8)
      ) THEN

यह स्थिति थोड़ी अधिक महंगी है, लेकिन फिर भी एक सूचकांक का उपयोग कर सकते हैं। ऊपर से मल्टी-कॉलम इंडेक्स काम करेगा - अगर आपको इसकी आवश्यकता है तो भी। या, थोड़ा अधिक कुशल, नाम पर एक साधारण अनुक्रमणिका:

CREATE INDEX t_name_idx ON t (name);

जैसा कि आपने टिप्पणी की थी, प्रति नाम . में अधिकतम 8 अलग-अलग पंक्तियाँ हो सकती हैं , व्यवहार में कम। तो यह अभी भी तेज़ होना चाहिए।

अंतिम INSERT प्रदर्शन

अगर INSERT प्रदर्शन सर्वोपरि है, विशेष रूप से यदि कई प्रयास किए गए INSERT शर्त को विफल करते हैं, तो आप और अधिक कर सकते हैं:एक भौतिक दृश्य बनाएं जो पूर्व-एकत्रित मान हो प्रति नाम :

CREATE TABLE mv_t AS 
SELECT name, bit_or(value) AS value
FROM   t
GROUP  BY 1
ORDER  BY 1;

नाम यहां अद्वितीय होने की गारंटी है। मैं एक प्राथमिक कुंजी का उपयोग करूंगा नाम . पर वह अनुक्रमणिका प्रदान करने के लिए जिसका हम अनुसरण कर रहे हैं:

ALTER TABLE mv_t SET (fillfactor=90);

ALTER TABLE mv_t
ADD CONSTRAINT mv_t_pkey PRIMARY KEY(name) WITH (fillfactor=90);

फिर आपका INSERT इस तरह दिख सकता है:

WITH i(n,v) AS (SELECT 'a'::text, B'10101010'::bit(8)) 
INSERT INTO t (name, value)
SELECT n, v
FROM   i
LEFT   JOIN mv_t m ON m.name = i.n
                  AND m.value & i.v <> B'00000000'::bit(8)
WHERE  m.n IS NULL;          -- alternative syntax for EXISTS (...)

fillfactor केवल तभी उपयोगी होता है जब आपकी तालिका को बहुत सारे अपडेट मिलते हैं।

नाम, मान या DELETE के डालने या अद्यतन करने के बाद ट्रिगर में भौतिक दृश्य में पंक्तियों को अपडेट करें इसे चालू रखने के लिए। अतिरिक्त वस्तुओं की लागत को लाभ के विरुद्ध तौलना होगा। काफी हद तक आपके सामान्य भार पर निर्भर करता है।




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. पोस्टग्रेज में रन टाइम संदेशों को प्रिंट करना

  2. postgresql टाइमस्टैम्प से std::chrono value

  3. जावा का उपयोग करके PostgreSQL में बाइटा से फ़ाइल प्राप्त करना

  4. पोस्टग्रेस बिट डेटा प्रकार को कैसे संभालता है?

  5. Postgres '\connect कमांड का JDBC प्रतिरूप क्या है?