यद्यपि यह आश्चर्य करना अच्छा है कि यह कैसे समझाया जा सकता है कि आप अक्सर एक ही क्रम देखते हैं, मैं यह बताना चाहता हूं कि अंतर्निहित डेटाबेस इंजन के विशेष कार्यान्वयन के कारण निहित आदेश पर भरोसा करना कभी भी अच्छा विचार नहीं है। दूसरे शब्दों में, यह जानना अच्छा है कि क्यों, लेकिन आपको कभी भी इस पर भरोसा नहीं करना चाहिए। एमएस एसक्यूएल के लिए, केवल एक चीज जो एक निश्चित क्रम में पंक्तियों को विश्वसनीय रूप से वितरित करती है, एक स्पष्ट ORDER BY
है खंड।
न केवल अलग-अलग RDMBS-es अलग-अलग व्यवहार करते हैं, एक विशेष उदाहरण अपडेट (पैच) के कारण अलग तरह से व्यवहार कर सकता है। इतना ही नहीं, RDBMS सॉफ़्टवेयर की स्थिति पर भी प्रभाव पड़ सकता है:एक "गर्म" डेटाबेस एक "ठंडे" से अलग व्यवहार करता है, एक छोटी तालिका एक बड़े से अलग व्यवहार करती है।
यहां तक कि अगर आपके पास कार्यान्वयन के बारे में पृष्ठभूमि की जानकारी है (उदाहरण:"एक क्लस्टर इंडेक्स है, इस प्रकार यह संभावना है कि डेटा क्लस्टर इंडेक्स के क्रम में वापस आ जाएगा"), हमेशा एक संभावना है कि कोई अन्य तंत्र है जिसे आप नहीं करते हैं ' इसके बारे में पता नहीं है कि पंक्तियों को एक अलग क्रम में वापस करने का कारण बनता है (उदा:"यदि किसी अन्य सत्र ने एक स्पष्ट ORDER BY
के साथ एक पूर्ण तालिका स्कैन किया है परिणामसेट कैश किया गया हो सकता है; बाद में पूर्ण स्कैन कैश से पंक्तियों को वापस करने का प्रयास करेगा"; ex2:"a GROUP BY
डेटा को सॉर्ट करके कार्यान्वित किया जा सकता है, इस प्रकार पंक्तियों को वापस करने के क्रम को प्रभावित करता है"; ex3:"यदि चयनित कॉलम सभी सेकेंडरी इंडेक्स में हैं जो पहले से ही मेमोरी में कैश्ड है, तो इंजन टेबल के बजाय सेकेंडरी इंडेक्स को स्कैन कर सकता है, माध्यमिक अनुक्रमणिका के क्रम से पंक्तियों को वापस करने की सबसे अधिक संभावना है")।
यहां एक बहुत ही सरल परीक्षण है जो मेरे कुछ बिंदुओं को दिखाता है।
सबसे पहले, स्टार्टअप SQL सर्वर (मैं 2008 का उपयोग कर रहा हूं)। यह तालिका बनाएं:
create table test_order (
id int not null identity(1,1) primary key
, name varchar(10) not null
)
तालिका की जांच करें और देखें कि primary key
. का समर्थन करने के लिए एक संकुल अनुक्रमणिका बनाई गई थी id
. पर कॉलम। उदाहरण के लिए, sql सर्वर प्रबंधन स्टूडियो में, आप ट्री व्यू का उपयोग कर सकते हैं और अपनी तालिका के नीचे अनुक्रमणिका फ़ोल्डर में नेविगेट कर सकते हैं। वहां आपको एक इंडेक्स देखना चाहिए, जिसका नाम इस प्रकार है:PK__test_ord__3213E83F03317E3D (Clustered)
इस कथन के साथ पहली पंक्ति डालें:
insert into test_order(name)
select RAND()
इस कथन को 16 बार दोहराकर और पंक्तियाँ सम्मिलित करें:
insert into test_order(name)
select RAND()
from test_order
अब आपके पास 65536 पंक्तियाँ होनी चाहिए:
select COUNT(*)
from test_order
अब, बिना किसी आदेश का उपयोग किए सभी पंक्तियों का चयन करें:
select *
from test_order
सबसे अधिक संभावना है, परिणाम प्राथमिक कुंजी के क्रम से लौटाए जाएंगे (हालांकि इसकी कोई गारंटी नहीं है)। यहाँ मुझे जो परिणाम मिला है (जो वास्तव में प्राथमिक कुंजी के क्रम से है):
# id name
1 1 0.605831
2 2 0.517251
3 3 0.52326
. . .......
65536 65536 0.902214
(# एक कॉलम नहीं है बल्कि परिणाम में पंक्ति की क्रमिक स्थिति है)
अब, name
. पर एक सेकेंडरी इंडेक्स बनाएं कॉलम:
create index idx_name on test_order(name)
सभी पंक्तियों का चयन करें, लेकिन केवल name
को पुनः प्राप्त करें कॉलम:
select name
from test_order
सबसे अधिक संभावना है कि परिणाम द्वितीयक अनुक्रमणिका idx_name के क्रम से लौटाए जाएंगे, क्योंकि क्वेरी को केवल अनुक्रमणिका को स्कैन करके हल किया जा सकता है (i.o.w. idx_name
एक आवरण है अनुक्रमणिका)। यहाँ मुझे जो परिणाम मिला है, वह वास्तव में name
. के क्रम से है ।
# name
1 0.0185732
2 0.0185732
. .........
65536 0.981894
अब, सभी कॉलम और सभी पंक्तियों को फिर से चुनें:
select *
from test_order
यह रहा मुझे मिला परिणाम:
# id name
1 17 0.0185732
2 18 0.0185732
3 19 0.0185732
... .. .........
जैसा कि आप देख सकते हैं, पहली बार हमने इस क्वेरी को चलाने से काफी अलग। (ऐसा लगता है कि पंक्तियों को द्वितीयक अनुक्रमणिका द्वारा क्रमित किया गया है, लेकिन मेरे पास कोई स्पष्टीकरण नहीं है कि ऐसा क्यों होना चाहिए)।
वैसे भी, लब्बोलुआब यह है - निहित आदेश पर भरोसा मत करो। आप स्पष्टीकरण के बारे में सोच सकते हैं कि एक विशेष आदेश क्यों देखा जा सकता है, लेकिन फिर भी आप कार्यान्वयन और रनटाइम स्थिति के बारे में गहन ज्ञान के बिना हमेशा इसकी भविष्यवाणी नहीं कर सकते (जैसे बाद के मामले में)।