किस बिंदु पर एक डेटाबेस लेनदेन में अपने अनुक्रमित को अद्यतन करता है?


11

मैं आवेषण में घटनाओं के अनुक्रम को समझने की कोशिश कर रहा हूं जहां एक सूचकांक और एक लेनदेन दोनों शामिल हैं।

उदाहरण के लिए, ओरेकल प्रलेखन राज्यों:

यदि आप डेटा लोड करने से पहले एक या एक से अधिक इंडेक्स बनाते हैं या बनाते हैं, तो डेटाबेस को हर इंडेक्स को अपडेट करना चाहिए क्योंकि प्रत्येक पंक्ति को डाला जाता है।

लेकिन क्या होता है अगर मैं एक लेन-देन बनाता हूं, तो पांच पंक्तियों को सम्मिलित करता हूं, फिर कमिट करता हूं? क्या इंडेक्स हर प्रविष्टि के लिए अपडेट किए गए हैं, या सिर्फ कमिट बिंदु पर हैं?

लॉजिक मुझे बताता है कि वे केवल कमिट पॉइंट पर अपडेट किए जाएंगे, क्योंकि एक अपडेटेड इंडेक्स संभवतः तब तक उपयोग में नहीं लाया जा सकता जब तक कि वे रिकॉर्ड नहीं किए जाते। लेकिन क्या यह सच है?

यदि ऐसा है, जब मेरे पास डालने के लिए 1 मी पंक्तियाँ हैं, तो सबसे अच्छे प्रदर्शन के लिए मुझे सभी पंक्तियों की एक बड़ी प्रतिबद्धता करनी चाहिए न कि 100k रिकॉर्ड के 10 लेनदेन? निश्चित रूप से मुझे यह पता चलता है कि यदि पंक्ति 999,999 विफल हो जाती है तो यह एक बड़ा रोलबैक है।

माफी अगर मेरी शब्दावली थोड़ी बाहर है। मैं व्यापार से डीबीए नहीं हूं। मैं किसी विशेष डेटाबेस में सामान्य रूप से डेटाबेस के रूप में बहुत दिलचस्पी नहीं रखता हूं, हालांकि ओरेकल और पोस्टग्रैज वही हैं जो मैं सबसे अधिक उपयोग करता हूं। मैंने इस विषय पर खोज की है, लेकिन वास्तव में निश्चित उत्तर नहीं पा सकता है।

जवाबों:


8

मैं SQL सर्वर और Oracle के साथ काम करता हूं। संभवतः कुछ अपवाद हैं, लेकिन उन प्लेटफार्मों के लिए सामान्य उत्तर यह है कि डेटा और इंडेक्स एक ही समय में अपडेट किए जाएंगे।

मुझे लगता है कि जब सत्र उस सत्र के लिए अद्यतन किए जाते हैं जो लेन-देन का मालिक होता है और अन्य सत्रों के बीच अंतर करने में मदद मिलती है। डिफ़ॉल्ट रूप से, अन्य सत्र अपडेट किए गए अनुक्रमणिकाओं को तब तक नहीं देखेंगे जब तक कि लेन-देन प्रतिबद्ध न हो। हालाँकि, लेन-देन का स्वामी वाला सत्र तुरंत अपडेट किए गए अनुक्रमित को देखेगा।

इसके बारे में सोचने के एक तरीके के लिए, एक प्राथमिक कुंजी के साथ एक मेज पर विचार करें। SQL Server और Oracle में इसे इंडेक्स के रूप में लागू किया जाता है। अधिकांश समय हम चाहते हैं कि यदि कोई INSERTऐसा किया जाता है तो तुरंत त्रुटि होगी जो प्राथमिक कुंजी का उल्लंघन होगा। ऐसा होने के लिए सूचकांक को डेटा के रूप में उसी समय अपडेट किया जाना चाहिए। ध्यान दें कि अन्य प्लेटफ़ॉर्म, जैसे पोस्टग्रैज़, स्थगित बाधाओं को अनुमति देते हैं, जो केवल लेनदेन के लिए प्रतिबद्ध होने पर जाँच की जाती है।

यहां एक त्वरित ओरेकल डेमो दिखाया गया है जो एक सामान्य मामला है:

CREATE TABLE X_TABLE (PK INT NULL, PRIMARY KEY (PK));

INSERT INTO X_TABLE VALUES (1);
INSERT INTO X_TABLE VALUES (1); -- no commit

दूसरा INSERTकथन एक त्रुटि फेंकता है:

SQL त्रुटि: ORA-00001: अद्वितीय बाधा (XXXXXX.SYS_C00384850) का उल्लंघन किया गया

00001. 00000 - "अद्वितीय बाधा (% s।% S) का उल्लंघन"

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

* कार्रवाई: या तो अद्वितीय प्रतिबंध हटा दें या कुंजी न डालें।

यदि आप नीचे एक इंडेक्स अपडेट कार्रवाई देखना पसंद करते हैं, तो SQL सर्वर में एक सरल डेमो है। पहले एक लाख पंक्तियों के साथ दो स्तंभ तालिका बनाएँ और VALस्तंभ पर एक गैर-अनुक्रमित सूचकांक :

DROP TABLE IF EXISTS X_TABLE_IX;

CREATE TABLE X_TABLE_IX (
ID INT NOT NULL,
VAL VARCHAR(10) NOT NULL
PRIMARY KEY (ID)
);

CREATE INDEX X_INDEX ON X_TABLE_IX (VAL);

-- insert one million rows with N from 1 to 1000000
INSERT INTO X_TABLE_IX
SELECT N, N FROM dbo.Getnums(1000000);

निम्नलिखित क्वेरी गैर-अनुक्रमित सूचकांक का उपयोग कर सकती है क्योंकि सूचकांक उस क्वेरी के लिए एक कवरिंग इंडेक्स है। इसमें निष्पादित करने के लिए आवश्यक सभी डेटा शामिल हैं। उम्मीद के मुताबिक कोई रिटर्न नहीं मिला है।

SELECT *
FROM X_TABLE_IX
WHERE VAL = 'A';

प्रश्न १

अब एक लेनदेन शुरू करते हैं और VALतालिका की लगभग सभी पंक्तियों के लिए अपडेट करते हैं:

BEGIN TRANSACTION

UPDATE X_TABLE_IX
SET VAL = 'A'
WHERE ID <> 1;

यहाँ उस के लिए क्वेरी योजना का हिस्सा है:

प्रश्न २

लाल रंग में परिचालित नॉनक्लेस्टेड इंडेक्स का अपडेट है। नीले रंग में परिचालित क्लस्टर इंडेक्स का अपडेट है, जो मूल रूप से टेबल का डेटा है। भले ही लेनदेन प्रतिबद्ध नहीं है, हम देखते हैं कि डेटा और इंडेक्स क्वेरी के निष्पादन के हिस्से में अपडेट किए जाते हैं। ध्यान दें कि आप इसे संभवतः किसी अन्य कारक के साथ शामिल डेटा के आकार के आधार पर किसी योजना में नहीं देखेंगे।

लेन-देन अभी भी प्रतिबद्ध नहीं है, तो SELECTऊपर से क्वेरी को फिर से देखें।

SELECT *
FROM X_TABLE_IX
WHERE VAL = 'A';

यहाँ छवि विवरण दर्ज करें

क्वेरी ऑप्टिमाइज़र अभी भी सूचकांक का उपयोग करने में सक्षम है और इस बार यह अनुमान लगाता है कि 999999 पंक्तियाँ वापस आ जाएंगी। क्वेरी निष्पादित करने से अपेक्षित परिणाम मिलता है।

यह एक सरल डेमो था, लेकिन उम्मीद है कि इससे चीजें थोड़ी साफ हो गईं।

एक तरफ के रूप में, मुझे कुछ मामलों के बारे में पता है जिसमें यह तर्क दिया जा सकता है कि एक सूचकांक तुरंत अपडेट नहीं किया गया है। यह प्रदर्शन कारणों से किया जाता है और अंतिम उपयोगकर्ता को असंगत डेटा देखने में सक्षम नहीं होना चाहिए। उदाहरण के लिए, कभी-कभी हटाए गए SQL सर्वर में अनुक्रमणिका पर पूरी तरह से लागू नहीं होगा। एक पृष्ठभूमि प्रक्रिया चलती है और अंततः डेटा को साफ करती है। यदि आप उत्सुक हैं तो आप भूत रिकॉर्ड के बारे में पढ़ सकते हैं ।


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

संबंधित प्रश्न (जब एक बाधा का उल्लंघन होगा) से संबंधित है कि क्या आप आस्थगित लेनदेन का उपयोग करते हैं या नहीं। उदाहरण के लिए, SQL सर्वर ने स्थगित लेन-देन को लागू नहीं किया है, इसलिए सभी उल्लंघन बयानों के अंत में होते हैं। अन्य DBMS में है (उदाहरण के लिए पोस्टग्रैज, हालांकि सभी प्रकार की बाधाओं के लिए नहीं), इसलिए जब आप एक बाधा को टाल दिया जाता है, तो लेनदेन के प्रतिबद्ध चरण में उल्लंघन की जांच की जाएगी)।
ypercube y

ओरेकल भी टाल बाधाओं का समर्थन करता है
BobC

1

मेरा अनुभव यह है कि 1,000,000 पंक्ति सम्मिलित करने के लिए वास्तव में अधिक संसाधनों की आवश्यकता होगी और यदि आपने बैच आवेषण का उपयोग किया है तो इसे पूरा करने में अधिक समय लगेगा। इसे 10,000 पंक्तियों के 100 आवेषण में एक उदाहरण के रूप में लागू किया जा सकता है।

इससे बैचों के ओवरहेड को कम किया जाता है और, यदि कोई बैच विफल हो जाता है, तो यह एक छोटा रोलबैक है।

किसी भी स्थिति में, SQL सर्वर के लिए एक bcp उपयोगिता या BULK INSERT कमांड है जिसका उपयोग बैच आवेषण करने के लिए किया जा सकता है।

और, ज़ाहिर है, आप इस दृष्टिकोण को संभालने के लिए खुद का कोड भी लागू कर सकते हैं।


1
सामान्य तौर पर, यदि आपको एक मेज पर बड़ी संख्या में पंक्तियों को सम्मिलित करने की आवश्यकता होती है जिसमें सूचकांक की आवश्यकता होती है, तो सूचकांक को छोड़ने, डेटा को लोड करने और फिर सूचकांक को फिर से बनाने के लिए तेज़ होने की संभावना है। ओरेकल / * + APPEND * / संकेत का उपयोग करते हुए एक सीधा पथ बल्क लोड विकल्प का भी समर्थन करता है।
BobC
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.