यह प्रश्न गुमराह करने वाली धारणा बनाता है कि प्राथमिक कुंजी तालिका क्रम को बिल्कुल लागू करती है। यह नहीं है। PostgreSQL तालिकाओं में प्राथमिक कुंजी के साथ या उसके बिना कोई परिभाषित क्रम नहीं होता है; वे पेज ब्लॉक में व्यवस्थित पंक्तियों का "ढेर" हैं। ORDER BY
. का उपयोग करके आदेश दिया जाता है वांछित होने पर प्रश्नों का खंड।
आप सोच रहे होंगे कि PostgreSQL टेबल को इंडेक्स-ओरिएंटेड टेबल के रूप में संग्रहीत किया जाता है जो प्राथमिक कुंजी क्रम में डिस्क पर संग्रहीत होते हैं, लेकिन ऐसा नहीं है कि Pg कैसे काम करता है। मुझे लगता है कि InnoDB प्राथमिक कुंजी द्वारा आयोजित तालिकाओं को संग्रहीत करता है (लेकिन चेक नहीं किया गया है), और यह कुछ अन्य विक्रेताओं के डेटाबेस में वैकल्पिक है जिसे अक्सर "क्लस्टर इंडेक्स" या "इंडेक्स-ऑर्गनाइज्ड टेबल" कहा जाता है। यह सुविधा वर्तमान में PostgreSQL (9.3 तक कम से कम) द्वारा समर्थित नहीं है।
उस ने कहा, PRIMARY KEY
एक UNIQUE
. का उपयोग करके कार्यान्वित किया जाता है सूचकांक, और उस सूचकांक के लिए एक आदेश है। इसे अनुक्रमणिका के बाएं कॉलम (और इसलिए प्राथमिक कुंजी) से आरोही क्रम में क्रमबद्ध किया जाता है, जैसे कि यह ORDER BY col1 ASC, col2 ASC, col3 ASC;
. पोस्टग्रेएसक्यूएल में किसी भी अन्य बी-पेड़ (जीआईएसटी या जीआईएन से अलग) इंडेक्स के बारे में भी यही सच है, क्योंकि वे बी + ट्रीज़ का उपयोग करके कार्यान्वित किए जाते हैं।
तो तालिका में:
CREATE TABLE demo (
a integer,
b text,
PRIMARY KEY(a,b)
);
सिस्टम स्वचालित रूप से इसके समकक्ष बना देगा:
CREATE UNIQUE INDEX demo_pkey ON demo(a ASC, b ASC);
जब आप कोई तालिका बनाते हैं, तो इसकी सूचना आपको दी जाती है, जैसे:
regress=> CREATE TABLE demo (
regress(> a integer,
regress(> b text,
regress(> PRIMARY KEY(a,b)
regress(> );
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "demo_pkey" for table "demo"
CREATE TABLE
तालिका की जांच करते समय आप इस सूचकांक को देख सकते हैं:
regress=> \d demo
Table "public.demo"
Column | Type | Modifiers
--------+---------+-----------
a | integer | not null
b | text | not null
Indexes:
"demo_pkey" PRIMARY KEY, btree (a, b)
आप CLUSTER
कर सकते हैं इस सूचकांक पर प्राथमिक कुंजी के अनुसार तालिका को फिर से व्यवस्थित करने के लिए, लेकिन यह एक बार का ऑपरेशन है। सिस्टम उस क्रम को बनाए नहीं रखेगा - हालांकि अगर गैर-डिफ़ॉल्ट FILLFACTOR
के कारण पृष्ठों में जगह खाली है मुझे लगता है कि यह कोशिश करेगा।
अनुक्रमणिका (लेकिन ढेर नहीं) के अंतर्निहित क्रम का एक परिणाम यह है कि यह बहुत है खोजने के लिए तेज़:
SELECT * FROM demo ORDER BY a, b;
SELECT * FROM demo ORDER BY a;
से:
SELECT * FROM demo ORDER BY a DESC, b;
और इनमें से कोई भी प्राथमिक कुंजी अनुक्रमणिका का उपयोग बिल्कुल भी नहीं कर सकता है, वे एक seqscan करेंगे जब तक कि आपके पास b
पर कोई अनुक्रमणिका न हो :
SELECT * FROM demo ORDER BY b, a;
SELECT * FROM demo ORDER BY b;
ऐसा इसलिए है क्योंकि PostgreSQL (a,b)
. पर एक इंडेक्स का उपयोग कर सकता है (a)
. पर एक इंडेक्स जितना तेज़ अकेला। यह (a,b)
. पर किसी अनुक्रमणिका का उपयोग नहीं कर सकता मानो यह (b)
. पर एक अनुक्रमणिका हो अकेला - धीरे-धीरे भी नहीं, बस नहीं कर सकता।
जहां तक DESC
का संबंध है प्रविष्टि, उसके लिए एक पीजी को रिवर्स इंडेक्स स्कैन करना होगा, जो सामान्य फॉरवर्ड इंडेक्स स्कैन से धीमा है। अगर आपको EXPLAIN ANALYZE
. में बहुत सारे रिवर्स इंडेक्स स्कैन दिखाई दे रहे हैं और आप DESC
में फ़ील्ड पर एक इंडेक्स बनाने के लिए अतिरिक्त इंडेक्स की प्रदर्शन लागत वहन कर सकते हैं आदेश।
यह WHERE
. के लिए सही है खंड, न केवल ORDER BY
. आप (a,b)
. पर एक इंडेक्स का उपयोग कर सकते हैं WHERE a = 4
. को खोजने के लिए या WHERE a = 4 AND b = 3
लेकिन नहीं खोजने के लिए WHERE b = 3
अकेला।