2010-04-21 15 views
33

मेरे पास लगभग 5 मिलियन पंक्तियों वाली एक तालिका है जिसमें एक एफके बाधा है जो किसी अन्य तालिका (लगभग 5 मिलियन पंक्तियों) की प्राथमिक कुंजी का संदर्भ देती है।PostgreSQL - बाधाओं को अक्षम करना

मुझे दोनों टेबलों से लगभग 75000 पंक्तियों को हटाने की आवश्यकता है। मुझे पता है कि अगर मैं इसे एफके बाधा के साथ करने की कोशिश करता हूं तो यह एक अस्वीकार्य समय लेने जा रहा है।

ओरेकल पृष्ठभूमि से आ रहा है मेरा पहला विचार बाधा को अक्षम करना था, & हटाएं तो बाधा को पुनः प्राप्त करें। यदि मैं एक सुपर उपयोगकर्ता हूं (मैं नहीं हूं, लेकिन मैं उस उपयोगकर्ता के रूप में लॉग इन कर रहा हूं जो ऑब्जेक्ट्स का स्वामित्व/निर्माण करता है) में पोस्टग्रेस मुझे बाधा ट्रिगर्स को अक्षम करने देता है, लेकिन ऐसा लगता है कि मैं काफी कुछ नहीं चाहता हूं।

दूसरा विकल्प बाधा को छोड़ना और फिर इसे बहाल करना है। मुझे चिंता है कि बाधाओं का पुनर्निर्माण करने से मेरी टेबल के आकार को उम्र बढ़ने जा रहा है।

कोई विचार?

संपादित करें: बिली के प्रोत्साहन के बाद मैंने किसी भी बाधा को बदले बिना हटाए जाने की कोशिश की है और इसमें 10 मिनट से ज्यादा समय लगता है। हालांकि, मैंने पाया है कि जिस तालिका से मैं हटाने की कोशिश कर रहा हूं वह एक स्व-रेफरेंशियल विदेशी कुंजी है ... डुप्लिकेट (& गैर अनुक्रमित)।

अंतिम अपडेट - मैंने स्वयं रेफरेंसियल विदेशी कुंजी गिरा दी, मेरी हटा दी और इसे वापस जोड़ा। बिली का सही दौर लेकिन दुर्भाग्य से मैं जवाब के रूप में अपनी टिप्पणी स्वीकार नहीं कर सकता!

+4

तो यह और भी 5 लाख पंक्तियों के साथ, कि समय लग रहा है, तो आप कुछ सेटअप गलत है। –

+0

क्या? हटाएं या बाधा को पुनः सक्षम करना? और हां, यह काफी संभव है कि कुछ गलत तरीके से स्थापित किया गया हो या अनुकूलित तरीके से कम में - डेटाबेस को हाइबरनेट द्वारा 'निर्मित' किया गया है (मुझे इसके साथ कुछ लेना देना नहीं था)। – azp74

+10

हटाएं। अनुक्रमित तालिकाओं से एफके चेक रैखिक समय लेता है, और 75000 + 75000 पंक्तियों = 150 000 पंक्तियों को हटा देता है। एफके चेक (बाइनरी सर्च, एलजी (5 मिलियन) == 1 9) प्रति तुलना में सबसे खराब मामले पर विचार करें, और शायद प्रति पंक्ति तुलना की 20 मशीन तुलना, 57 000 000 तुलना के बराबर है। एक औसत तुलना में एक अरब तुलना करने में सक्षम होने वाली औसत मशीन का एक रूढ़िवादी अनुमान ध्यान में रखते हुए, यह अभी भी CPU समय के एक सेकंड से कम लेना चाहिए। डिस्क से लोड करना भी एक बड़ा मुद्दा नहीं होना चाहिए क्योंकि तालिका में 5 मिलियन पंक्तियों पर भी तालिका में फिट होना चाहिए। –

उत्तर

42

पिछली टिप्पणियों के अनुसार, यह एक समस्या होनी चाहिए। उस ने कहा, एक ऐसा आदेश है जो आप देख रहे हैं - यह बाधाओं को स्थगित करने के लिए सेट करेगा ताकि उन्हें COMMIT पर चेक किया जा सके, हर डिलीट पर नहीं। यदि आप सभी पंक्तियों में से केवल एक बड़ा हटाना कर रहे हैं, तो इससे कोई फर्क नहीं पड़ता है, लेकिन यदि आप इसे टुकड़ों में कर रहे हैं, तो यह होगा।

SET CONSTRAINTS ALL DEFERRED 

वह है जो आप उस मामले में ढूंढ रहे हैं। ध्यान दें कि स्थगित होने से पहले बाधाओं को DEFERRABLE के रूप में चिह्नित किया जाना चाहिए। उदाहरण के लिए:

ALTER TABLE table_name 
    ADD CONSTRAINT constraint_uk UNIQUE(column_1, column_2) 
    DEFERRABLE INITIALLY IMMEDIATE; 

बाधा तो लेन-देन या समारोह में आस्थगित किया जा सकता है इस प्रकार है:

CREATE OR REPLACE FUNCTION f() RETURNS void AS 
$BODY$ 
BEGIN 
    SET CONSTRAINTS ALL DEFERRED; 

    -- Code that temporarily violates the constraint... 
    -- UPDATE table_name ... 
END; 
$BODY$ 
    LANGUAGE plpgsql VOLATILE 
    COST 100; 
+1

निश्चित रूप से प्रयास करने लायक है, लेकिन मुझे विश्वास नहीं है कि स्थगित बाधाएं तेजी से हैं। AFAIK वे सिर्फ सत्यापन कार्य को DELETE-time से COMMIT-time में स्थानांतरित करते हैं। – intgr

+1

मैं इसे एक जाना था लेकिन एफके छोड़ना और इसे काम बहाल करना होगा। Intgr की तरह, मुझे आश्चर्य है कि यह सिर्फ समय के लिए एफके की जांच में बदलाव नहीं करेगा, इसलिए मैं इसे अगली बार याद रखूंगा। – azp74

+1

मैंने डेटाबेस छोड़ दिया और 'SET CONSTRAINTS ALL DEFERRED 'चलाने के बाद इसे फिर से आयात किया। एक बार आयात किए जाने के बाद इन बाधाओं को "पुनः सक्षम" करने का कोई तरीका है? यह एक बहुत बड़ी फाइल है, इसलिए टेबल निर्माण को पुन: क्रमबद्ध करना बहुत कठिन होगा। मैं डेटा को दो बार आयात करके इससे पहले मिल गया था। – taco

-7

सभी अक्षम तालिका की कमी

ALTER TABLE TableName NOCHECK CONSTRAINT ConstraintName 

- सभी तालिका की कमी सक्षम

ALTER TABLE TableName CHECK CONSTRAINT ConstraintName 
+3

प्रश्न Postgresql के बारे में था जिसमें उस क्षमता (v9.4 के रूप में) नहीं है। –

+0

सहमत v9.4 में यह सुविधा नहीं है त्रुटि: "NOCHECK" पर या उसके पास वाक्यविन्यास त्रुटि लाइन 1: वैकल्पिक तालिका तालिका नामक कन्स्ट्रेंट कॉन्स्ट्रेनेट नाम –

3

(यह उत्तर मानता है कि इन इरादों की सभी पंक्तियों को हटाने के लिए आपका इरादा सिर्फ एक चयन नहीं है।)

मुझे यह भी करना था, लेकिन परीक्षण सूट के हिस्से के रूप में। मुझे जवाब मिला, elsewhere on SO का सुझाव दिया।इस प्रकार TRUNCATE TABLE का उपयोग करें:

TRUNCATE TABLE <list-of-table-names> [RESTART IDENTITY] [CASCADE]; 

जल्दी से निम्नलिखित प्रदान की वहाँ तालिकाओं से इन तालिकाओं की पंक्तियों का कोई सन्दर्भ में सूचीबद्ध नहीं हैं कि, टेबल table1, table2, और table3 से सभी पंक्तियों को हटाता है:

TRUNCATE TABLE table1, table2, table3; 

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

हालांकि, अगर आप क्वेरी अर्हता प्राप्त कर सकते हैं इतना है कि यह भी सूचीबद्ध तालिकाओं को संदर्भ के साथ सभी तालिकाओं ट्रंकेटस (हालांकि मैं इस प्रयास नहीं किया है):

TRUNCATE TABLE table1, table2, table3 CASCADE; 

डिफ़ॉल्ट रूप से, इन तालिकाओं के दृश्यों नहीं है नंबरिंग पुनरारंभ करें। अनुक्रम की अगली संख्या के साथ नई पंक्तियां जारी रहेगी। अनुक्रम नंबर को पुनः आरंभ करने के लिए:

TRUNCATE TABLE table1, table2, table3 RESTART IDENTITY; 
7

क्या मेरे लिए काम किया एक TRIGGERS उन तालिकाओं कि वाला DELETE आपरेशन में शामिल हो रहे हैं के द्वारा एक निष्क्रिय करने के लिए किया गया था।

ALTER TABLE reference DISABLE TRIGGER ALL; 
DELETE FROM reference WHERE refered_id > 1; 
ALTER TABLE reference ENABLE TRIGGER ALL; 

समाधान संस्करण 9.3.16 में काम कर रहा है। मेरे मामले में समय 45 मिनट से 14 सेकंड तक चला गया DELETE संचालन निष्पादित।

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

+1

ध्यान दें कि 'ALTER तालिका' आदेश निष्पादित PostgreSQL उपयोगकर्ता उस के स्वामी होना चाहिए तालिका। – amphetamachine

0

आप DISABLE TRIGGER ALL कोशिश करते हैं और permission denied: "RI_ConstraintTrigger_a_16428" is a system trigger की तरह कोई त्रुटि मिलती है (मैं अमेज़न आरडीएस पर यह मिल गया), इस प्रयास करें:

set session_replication_role to replica; 

इस सफल होता है, तो सभी ट्रिगर है कि मेज की कमी आबाद अक्षम हो जाएगा। अब यह सुनिश्चित करने के लिए आप पर निर्भर है कि आपके परिवर्तन डीबी को एक सतत स्थिति में छोड़ दें!

फिर जब आप समाप्त कर लें, फिर से सक्षम & की कमी के साथ अपने सत्र के लिए चलाता है:

set session_replication_role to default; 
संबंधित मुद्दे