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

TSTZRANGE को &&के साथ जोड़ने पर Postgresql 9.4 क्वेरी उत्तरोत्तर धीमी हो जाती है

बहिष्करण प्रतिबंध

मेरा सुझाव है कि आप इसके बजाय एक बहिष्करण बाधा का उपयोग करें, जो बहुत आसान, सुरक्षित और तेज़ है:

आपको अतिरिक्त मॉड्यूल स्थापित करने की आवश्यकता है btree_gist पहला। इस संबंधित उत्तर में निर्देश और स्पष्टीकरण देखें:

और आपको "ParentID" . शामिल करना होगा तालिका में "Bar" अनावश्यक रूप से, जो भुगतान करने के लिए एक छोटी सी कीमत होगी। तालिका परिभाषाएँ इस तरह दिख सकती हैं:

CREATE TABLE "Foo" (
   "FooID"    serial PRIMARY KEY
   "ParentID" int4 NOT NULL REFERENCES "Parent"
   "Details1" varchar
   CONSTRAINT foo_parent_foo_uni UNIQUE ("ParentID", "FooID")  -- required for FK
);

CREATE TABLE "Bar" (
   "ParentID"  int4 NOT NULL,
   "FooID"     int4 NOT NULL REFERENCES "Foo" ("FooID"),
   "Timerange" tstzrange NOT NULL,
   "Detail1"   varchar,
   "Detail2"   varchar,
   CONSTRAINT "Bar_pkey" PRIMARY KEY ("FooID", "Timerange"),
   CONSTRAINT bar_foo_fk
      FOREIGN KEY ("ParentID", "FooID") REFERENCES "Foo" ("ParentID", "FooID"),
   CONSTRAINT bar_parent_timerange_excl
      EXCLUDE USING gist ("ParentID" WITH =, "Timerange" WITH &&)
);

मैंने "Bar"."FooID" . के लिए डेटा प्रकार भी बदल दिया है <स्ट्राइक>int8 . से से int4 . यह "Foo"."FooID" . का संदर्भ देता है , जो एक serial . है , यानी int4 . मिलान प्रकार का प्रयोग करें int4 (या सिर्फ integer ) कई कारणों से, उनमें से एक प्रदर्शन है।

आपको अब किसी ट्रिगर की आवश्यकता नहीं है (कम से कम इस कार्य के लिए नहीं), और आप "Bar_FooID_Timerange_idx" अनुक्रमणिका नहीं बनाते हैं और भी, क्योंकि यह अपवर्जन बाधा द्वारा परोक्ष रूप से बनाया गया है।

("ParentID", "FooID") . पर एक btree अनुक्रमणिका हालांकि सबसे अधिक उपयोगी होगा:

CREATE INDEX bar_parentid_fooid_idx ON "Bar" ("ParentID", "FooID");

संबंधित:

मैंने UNIQUE ("ParentID", "FooID") . चुना है और इसके विपरीत किसी कारण से नहीं, क्योंकि एक अन्य अनुक्रमणिका है जिसमें प्रमुख "FooID" है किसी भी तालिका में:

इसके अलावा:मैं कभी भी डबल-उद्धृत CaMeL का उपयोग नहीं करता -केस पहचानकर्ता पोस्टग्रेज में। मैं इसे केवल आपके लेआउट का अनुपालन करने के लिए यहां करता हूं।

अनावश्यक कॉलम से बचें

यदि आप "Bar"."ParentID" . को शामिल नहीं कर सकते हैं या नहीं करेंगे तो अनावश्यक रूप से, एक और दुष्ट है रास्ता - इस शर्त पर कि "Foo"."ParentID" कभी अपडेट नहीं किया गया . सुनिश्चित करें कि, उदाहरण के लिए एक ट्रिगर के साथ।

आप एक IMMUTABLE को नकली बना सकते हैं समारोह:

CREATE OR REPLACE FUNCTION f_parent_of_foo(int)
  RETURNS int AS
'SELECT "ParentID" FROM public."Foo" WHERE "FooID" = $1'
  LANGUAGE sql IMMUTABLE;

मैंने public . मानते हुए, तालिका नाम को सुनिश्चित करने के लिए स्कीमा-योग्यता प्राप्त की है . अपने स्कीमा के अनुकूल बनें।

अधिक:

फिर इसे बहिष्करण बाधा में उपयोग करें:

   CONSTRAINT bar_parent_timerange_excl
      EXCLUDE USING gist (f_parent_of_foo("FooID") WITH =, "Timerange" WITH &&)

एक अनावश्यक int4 saving को सहेजते समय कॉलम, बाधा को सत्यापित करना अधिक महंगा होगा और संपूर्ण समाधान अधिक पूर्व शर्त पर निर्भर करता है।

संघर्ष संभालें

आप INSERT को लपेट सकते हैं और UPDATE एक plpgsql फ़ंक्शन में और बहिष्करण बाधा से संभावित अपवादों को ट्रैप करें (23P01 exclusion_violation ) इसे किसी तरह से संभालने के लिए।

INSERT ...

EXCEPTION
    WHEN exclusion_violation
    THEN  -- handle conflict

पूरा कोड उदाहरण:

पोस्टग्रेज 9.5 में विरोध को हैंडल करें

पोस्टग्रेज में 9.5 आप INSERT handle को संभाल सकते हैं सीधे नए "यूपीएसईआरटी" कार्यान्वयन के साथ। दस्तावेज:

हालांकि:

लेकिन आप अभी भी ON CONFLICT DO NOTHING . का उपयोग कर सकते हैं , इस प्रकार संभव exclusion_violation . से बचना अपवाद बस जांचें कि क्या कोई पंक्ति वास्तव में अपडेट की गई थी, जो कि सस्ता है:

INSERT ... 
ON CONFLICT ON CONSTRAINT bar_parent_timerange_excl DO NOTHING;

IF NOT FOUND THEN
   -- handle conflict
END IF;

यह उदाहरण चेक को दी गई बहिष्करण बाधा तक सीमित करता है। (मैंने उपरोक्त तालिका परिभाषा में इस उद्देश्य के लिए स्पष्ट रूप से बाधा का नाम दिया है।) अन्य संभावित अपवाद पकड़े नहीं गए हैं।




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. PostgreSQL प्रतिकृति सर्वोत्तम अभ्यास - भाग 2

  2. PostgreSQL डेटाबेस के साथ कैसे काम करें

  3. PostgreSQL:स्तंभ परिभाषा सूची का उपयोग किए बिना तालिका से गतिशील पंक्तियों को कैसे वापस करें?

  4. PostgreSQL में अनुक्रमणिका की विशिष्टता निकालें

  5. PL/pgSQL अनाम कोड ब्लॉक