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

INSERT / UPDATE / DELETE ऑपरेशन को ऑप्टिमाइज़ करें

संशोधित तालिका परिभाषा

यदि आपको वास्तव में उन स्तंभों की आवश्यकता है NOT NULL और आपको वास्तव में स्ट्रिंग की आवश्यकता है 'default' engine_slug . के लिए डिफ़ॉल्ट के रूप में , मैं कॉलम डिफ़ॉल्ट पेश करने की सलाह दूंगा:

COLUMN           |          TYPE           |      Modifiers
-----------------+-------------------------+---------------------
 id              | INTEGER                 | NOT NULL DEFAULT ... 
 engine_slug     | CHARACTER VARYING(200)  | NOT NULL DEFAULT 'default'
 content_type_id | INTEGER                 | NOT NULL
 object_id       | text                    | NOT NULL
 object_id_int   | INTEGER                 |
 title           | CHARACTER VARYING(1000) | NOT NULL
 description     | text                    | NOT NULL DEFAULT ''
 content         | text                    | NOT NULL
 url             | CHARACTER VARYING(1000) | NOT NULL DEFAULT ''
 meta_encoded    | text                    | NOT NULL DEFAULT '{}'
 search_tsv      | tsvector                | NOT NULL
 ...

DDL स्टेटमेंट होगा:

ALTER TABLE watson_searchentry ALTER COLUMN  engine_slug DEFAULT 'default';

आदि।

फिर आपको उन मानों को हर बार मैन्युअल रूप से सम्मिलित करने की आवश्यकता नहीं है।

साथ ही:object_id text NOT NULL, object_id_int INTEGER ? यह अजीब है। मुझे लगता है कि आपके पास अपने कारण हैं ...

मैं आपकी अद्यतन आवश्यकता के साथ जाऊंगा:

बेशक, आपको जरूरी एक अद्वितीय जोड़ें आपकी आवश्यकताओं को लागू करने में बाधा:

ALTER TABLE watson_searchentry
ADD CONSTRAINT ws_uni UNIQUE (content_type_id, object_id_int)

संलग्न सूचकांक का उपयोग किया जाएगा। शुरुआत के लिए इस क्वेरी के द्वारा।

बीटीडब्ल्यू, मैं लगभग कभी भी varchar(n) . का उपयोग नहीं करता हूं पोस्टग्रेज में। बस text . ये रहा एक कारण।

डेटा-संशोधित सीटीई के साथ क्वेरी

इसे एक एकल SQL क्वेरी के रूप में डेटा-संशोधित सामान्य तालिका अभिव्यक्तियों के साथ फिर से लिखा जा सकता है, जिसे "लिखने योग्य" CTE भी कहा जाता है। पोस्टग्रेज 9.1 या बाद के संस्करण की आवश्यकता है।
इसके अतिरिक्त, यह क्वेरी केवल वही हटाती है जिसे हटाया जाना है, और जो अपडेट किया जा सकता है उसे अपडेट करता है।

WITH  ctyp AS (
   SELECT id AS content_type_id
   FROM   django_content_type
   WHERE  app_label = 'web'
   AND    model = 'member'
   )
, sel AS (
   SELECT ctyp.content_type_id
         ,m.id       AS object_id_int
         ,m.id::text AS object_id       -- explicit cast!
         ,m.name     AS title
         ,concat_ws(' ', u.email,m.normalized_name,c.name) AS content
         -- other columns have column default now.
   FROM   web_user    u
   JOIN   web_member  m  ON m.user_id = u.id
   JOIN   web_country c  ON c.id = m.country_id
   CROSS  JOIN ctyp
   WHERE  u.is_active
   )
, del AS (     -- only if you want to del all other entries of same type
   DELETE FROM watson_searchentry w
   USING  ctyp
   WHERE  w.content_type_id = ctyp.content_type_id
   AND    NOT EXISTS (
      SELECT 1
      FROM   sel
      WHERE  sel.object_id_int = w.object_id_int
      )
   )
, up AS (      -- update existing rows
   UPDATE watson_searchentry 
   SET    object_id = s.object_id
         ,title     = s.title
         ,content   = s.content
   FROM   sel s
   WHERE  w.content_type_id = s.content_type_id
   AND    w.object_id_int   = s.object_id_int
   )
               -- insert new rows
INSERT  INTO watson_searchentry (
        content_type_id, object_id_int, object_id, title, content)
SELECT  sel.*  -- safe to use, because col list is defined accordingly above
FROM    sel
LEFT    JOIN watson_searchentry w1 USING (content_type_id, object_id_int)
WHERE   w1.content_type_id IS NULL;
  • django_content_type . पर सबक्वेरी हमेशा एक ही मूल्य देता है? अन्यथा, CROSS JOIN परेशानी पैदा कर सकता है।

  • पहला सीटीई sel डालने के लिए पंक्तियों को इकट्ठा करता है। ध्यान दें कि मैं मेल खाने वाले कॉलम नामों को कैसे चुनता हूं चीजों को आसान बनाने के लिए।

  • CTE del . में मैं उन पंक्तियों को हटाने से बचता हूँ जिन्हें अद्यतन किया जा सकता है।

  • CTE में up इसके बजाय उन पंक्तियों को अपडेट किया जाता है।

  • तदनुसार, मैं उन पंक्तियों को सम्मिलित करने से बचता हूँ जिन्हें पहले अंतिम INSERT . में हटाया नहीं गया था ।

बार-बार उपयोग के लिए आसानी से SQL या PL/pgSQL फ़ंक्शन में लपेटा जा सकता है।

भारी समवर्ती उपयोग के लिए सुरक्षित नहीं है। आपके पास मौजूद फ़ंक्शन से काफी बेहतर है, लेकिन समवर्ती लेखन के खिलाफ अभी भी 100% मजबूत नहीं है। लेकिन आपकी अद्यतन जानकारी के अनुसार यह कोई समस्या नहीं है।

अद्यतनों को DELETE और INSERT से बदलना बहुत अधिक महंगा हो सकता है या नहीं भी हो सकता है। MVCC के कारण आंतरिक रूप से प्रत्येक अद्यतन का परिणाम एक नई पंक्ति संस्करण में होता है। मॉडल

पहले गति करें

यदि आप वास्तव में पुरानी पंक्तियों को संरक्षित करने की परवाह नहीं करते हैं, तो आपका सरल दृष्टिकोण तेज़ हो सकता है:सब कुछ हटाएं और नई पंक्तियां डालें। साथ ही, एक plpgsql फ़ंक्शन में लपेटने से कुछ योजना ओवरहेड बचती है। आपका कार्य मूल रूप से, कुछ मामूली सरलीकरण और ऊपर जोड़े गए डिफ़ॉल्ट को देखकर:

CREATE OR REPLACE FUNCTION update_member_search_index()
  RETURNS VOID AS
$func$
DECLARE
   _ctype_id int := (
      SELECT id
      FROM   django_content_type
      WHERE  app_label='web'
      AND    model = 'member'
      );  -- you can assign at declaration time. saves another statement
BEGIN
   DELETE FROM watson_searchentry
   WHERE content_type_id = _ctype_id;

   INSERT INTO watson_searchentry
         (content_type_id, object_id, object_id_int, title, content)
   SELECT _ctype_id, m.id, m.id::int,m.name
         ,u.email || ' ' || m.normalized_name || ' ' || c.name
   FROM   web_member  m
   JOIN   web_user    u USING (user_id)
   JOIN   web_country c ON c.id = m.country_id
   WHERE  u.is_active;
END
$func$ LANGUAGE plpgsql;

मैं concat_ws() :यह NULL . से सुरक्षित है मूल्यों और कोड को सरल करता है, लेकिन साधारण संयोजन की तुलना में थोड़ा धीमा।

इसके अलावा:

इस फ़ंक्शन में तर्क को शामिल करना तेज़ होगा - यदि ट्रिगर की आवश्यकता केवल यही है। अन्यथा, यह शायद उपद्रव के लायक नहीं है।




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Postgres . में निकाले गए स्तंभों की सूची से मानों के लिए सरणी बनाएँ

  2. Psql सभी तालिकाओं को सूचीबद्ध करें

  3. PostgreSQL रिकॉर्ड के माध्यम से पुनरावृति। अगली पंक्ति से डेटा का संदर्भ कैसे लें?

  4. SQLException:यह परिणामसेट बंद है

  5. PostgreSQL में रेडियन () फ़ंक्शन कैसे काम करता है