क्या इसके लिए सभी चयनित कॉलमों को एक इंडेक्स को कवर करना होगा, जिनका उपयोग ORDER BY के लिए किया जाना है?


15

SO पर, किसी ने हाल ही में पूछा कि सूचकांक का उपयोग करके ORDER क्यों नहीं है?

स्थिति में तीन कॉलम और 10k पंक्तियों के साथ MySQL में एक साधारण InnoDB तालिका शामिल थी। स्तंभों में से एक, एक पूर्णांक, अनुक्रमित किया गया था - और ओपी ने उस स्तंभ पर क्रमबद्ध अपनी पूरी तालिका को पुनः प्राप्त करने की कोशिश की:

SELECT * FROM person ORDER BY age

उन्होंने EXPLAINयह कहते हुए आउटपुट संलग्न किया कि यह क्वेरी filesortइंडेक्स के बजाय () के साथ हल की गई थी और पूछा था कि ऐसा क्यों होगा।

बावजूद संकेत FORCE INDEX FOR ORDER BY (age) सूचकांक के कारण प्रयोग की जाने वाली , कोई जवाब है कि (दूसरों से टिप्पणी / upvotes समर्थन के साथ) एक सूचकांक केवल छँटाई जब चयनित स्तंभ अनुक्रमणिका से सभी को पढ़े गए हैं के लिए प्रयोग किया जाता है (यानी के रूप में सामान्य रूप से ने संकेत किया जाएगा Using indexमें Extraस्तंभ का EXPLAINउत्पादन)। बाद में एक स्पष्टीकरण दिया गया कि अनुक्रमणिका को ट्रेस करना और फिर तालिका से कॉलम प्राप्त करना यादृच्छिक I / O में परिणाम देता है, जिसे MySQL एक से अधिक महंगा मानता है filesort

यह ORDER BYऑप्टिमाइज़ेशन पर मैनुअल अध्याय के चेहरे पर उड़ान भरने के लिए प्रतीत होता है , जो न केवल उस मजबूत धारणा को व्यक्त करता है जो ORDER BYएक सूचकांक से संतुष्ट होकर अतिरिक्त छंटाई करने के लिए बेहतर है (वास्तव में, filesortएस्कॉर्ट और मर्जोर्ट का एक संयोजन है और इसलिए एक कम सीमा होनी चाहिए , जबकि क्रम में सूचकांक के माध्यम से चलना और तालिका में मांग करना - यह सही अर्थ बनाता है), लेकिन यह भी इस कथित "अनुकूलन" का उल्लेख करने की उपेक्षा करता है, जबकि यह भी बताते हुए:Ω(nlog n)O(n)

निम्नलिखित प्रश्न ORDER BYभाग को हल करने के लिए सूचकांक का उपयोग करते हैं :

SELECT * FROM t1
  ORDER BY key_part1,key_part2,... ;

मेरे पढ़ने के लिए, इस स्थिति में ठीक यही स्थिति है (फिर भी स्पष्ट संकेत के बिना सूचकांक का उपयोग नहीं किया जा रहा था)।

मेरे प्रश्न हैं:

  • क्या वास्तव में सभी चयनित स्तंभों को अनुक्रमित करने के लिए MySQL के लिए अनुक्रमित किया जाना आवश्यक है?

    • यदि हां, तो यह कहां से प्रलेखित है (यदि बिल्कुल)?

    • यदि नहीं, तो यहाँ क्या हो रहा था?

जवाबों:


14

क्या वास्तव में सभी चयनित स्तंभों को अनुक्रमित करने के लिए MySQL के लिए अनुक्रमित किया जाना आवश्यक है?

यह एक लोडेड प्रश्न है क्योंकि ऐसे कारक हैं जो यह निर्धारित करते हैं कि कोई इंडेक्स इस्तेमाल करने लायक है या नहीं।

FACTOR # 1

किसी भी सूचकांक के लिए, प्रमुख जनसंख्या क्या है? दूसरे शब्दों में, सूचकांक में दर्ज सभी tuples की कार्डिनैलिटी (विशिष्ट गणना) क्या है?

फैक्टरी # 2

आप किस स्टोरेज इंजन का उपयोग कर रहे हैं? क्या एक सूचकांक से सभी आवश्यक कॉलम सुलभ हैं?

आगे क्या होगा ???

चलो एक सरल उदाहरण लेते हैं: एक तालिका जिसमें दो मान होते हैं (पुरुष और महिला)

इंडेक्स के उपयोग के लिए परीक्षण के साथ ऐसी तालिका बनाएं

USE test
DROP TABLE IF EXISTS mf;
CREATE TABLE mf
(
    id int not null auto_increment,
    gender char(1),
    primary key (id),
    key (gender)
) ENGINE=InnODB;
INSERT INTO mf (gender) VALUES
('M'),('M'),('M'),('M'),('M'),('M'),('M'),('M'),
('M'),('M'),('M'),('M'),('F'),('F'),('M'),('M'),
('M'),('M'),('M'),('M'),('M'),('M'),('M'),('M'),
('M'),('M'),('M'),('M'),('M'),('M'),('M'),('M'),
('F'),('M'),('M'),('M'),('M'),('M'),('M'),('M');
ANALYZE TABLE mf;
EXPLAIN SELECT gender FROM mf WHERE gender='F';
EXPLAIN SELECT gender FROM mf WHERE gender='M';
EXPLAIN SELECT id FROM mf WHERE gender='F';
EXPLAIN SELECT id FROM mf WHERE gender='M';

परीक्षण InnoDB

mysql> USE test
Database changed
mysql> DROP TABLE IF EXISTS mf;
Query OK, 0 rows affected (0.00 sec)

mysql> CREATE TABLE mf
    -> (
    ->     id int not null auto_increment,
    ->     gender char(1),
    ->     primary key (id),
    ->     key (gender)
    -> ) ENGINE=InnoDB;
Query OK, 0 rows affected (0.07 sec)

mysql> INSERT INTO mf (gender) VALUES
    -> ('M'),('M'),('M'),('M'),('M'),('M'),('M'),('M'),
    -> ('M'),('M'),('M'),('M'),('F'),('F'),('M'),('M'),
    -> ('M'),('M'),('M'),('M'),('M'),('M'),('M'),('M'),
    -> ('M'),('M'),('M'),('M'),('M'),('M'),('M'),('M'),
    -> ('F'),('M'),('M'),('M'),('M'),('M'),('M'),('M');
Query OK, 40 rows affected (0.06 sec)
Records: 40  Duplicates: 0  Warnings: 0

mysql> ANALYZE TABLE mf;
+---------+---------+----------+----------+
| Table   | Op      | Msg_type | Msg_text |
+---------+---------+----------+----------+
| test.mf | analyze | status   | OK       |
+---------+---------+----------+----------+
1 row in set (0.00 sec)

mysql> EXPLAIN SELECT gender FROM mf WHERE gender='F';
+----+-------------+-------+------+---------------+--------+---------+-------+------+--------------------------+
| id | select_type | table | type | possible_keys | key    | key_len | ref   | rows | Extra                    |
+----+-------------+-------+------+---------------+--------+---------+-------+------+--------------------------+
|  1 | SIMPLE      | mf    | ref  | gender        | gender | 2       | const |    3 | Using where; Using index |
+----+-------------+-------+------+---------------+--------+---------+-------+------+--------------------------+
1 row in set (0.00 sec)

mysql> EXPLAIN SELECT gender FROM mf WHERE gender='M';
+----+-------------+-------+------+---------------+--------+---------+-------+------+--------------------------+
| id | select_type | table | type | possible_keys | key    | key_len | ref   | rows | Extra                    |
+----+-------------+-------+------+---------------+--------+---------+-------+------+--------------------------+
|  1 | SIMPLE      | mf    | ref  | gender        | gender | 2       | const |   37 | Using where; Using index |
+----+-------------+-------+------+---------------+--------+---------+-------+------+--------------------------+
1 row in set (0.00 sec)

mysql> EXPLAIN SELECT id FROM mf WHERE gender='F';
+----+-------------+-------+------+---------------+--------+---------+-------+------+--------------------------+
| id | select_type | table | type | possible_keys | key    | key_len | ref   | rows | Extra                    |
+----+-------------+-------+------+---------------+--------+---------+-------+------+--------------------------+
|  1 | SIMPLE      | mf    | ref  | gender        | gender | 2       | const |    3 | Using where; Using index |
+----+-------------+-------+------+---------------+--------+---------+-------+------+--------------------------+
1 row in set (0.00 sec)

mysql> EXPLAIN SELECT id FROM mf WHERE gender='M';
+----+-------------+-------+------+---------------+--------+---------+-------+------+--------------------------+
| id | select_type | table | type | possible_keys | key    | key_len | ref   | rows | Extra                    |
+----+-------------+-------+------+---------------+--------+---------+-------+------+--------------------------+
|  1 | SIMPLE      | mf    | ref  | gender        | gender | 2       | const |   37 | Using where; Using index |
+----+-------------+-------+------+---------------+--------+---------+-------+------+--------------------------+
1 row in set (0.00 sec)

mysql>

टेस्ट मेरा

mysql> USE test
Database changed
mysql> DROP TABLE IF EXISTS mf;
Query OK, 0 rows affected (0.00 sec)

mysql> CREATE TABLE mf
    -> (
    ->     id int not null auto_increment,
    ->     gender char(1),
    ->     primary key (id),
    ->     key (gender)
    -> ) ENGINE=MyISAM;
Query OK, 0 rows affected (0.05 sec)

mysql> INSERT INTO mf (gender) VALUES
    -> ('M'),('M'),('M'),('M'),('M'),('M'),('M'),('M'),
    -> ('M'),('M'),('M'),('M'),('F'),('F'),('M'),('M'),
    -> ('M'),('M'),('M'),('M'),('M'),('M'),('M'),('M'),
    -> ('M'),('M'),('M'),('M'),('M'),('M'),('M'),('M'),
    -> ('F'),('M'),('M'),('M'),('M'),('M'),('M'),('M');
Query OK, 40 rows affected (0.00 sec)
Records: 40  Duplicates: 0  Warnings: 0

mysql> ANALYZE TABLE mf;
+---------+---------+----------+----------+
| Table   | Op      | Msg_type | Msg_text |
+---------+---------+----------+----------+
| test.mf | analyze | status   | OK       |
+---------+---------+----------+----------+
1 row in set (0.00 sec)

mysql> EXPLAIN SELECT gender FROM mf WHERE gender='F';
+----+-------------+-------+------+---------------+--------+---------+-------+------+--------------------------+
| id | select_type | table | type | possible_keys | key    | key_len | ref   | rows | Extra                    |
+----+-------------+-------+------+---------------+--------+---------+-------+------+--------------------------+
|  1 | SIMPLE      | mf    | ref  | gender        | gender | 2       | const |    3 | Using where; Using index |
+----+-------------+-------+------+---------------+--------+---------+-------+------+--------------------------+
1 row in set (0.00 sec)

mysql> EXPLAIN SELECT gender FROM mf WHERE gender='M';
+----+-------------+-------+------+---------------+--------+---------+-------+------+--------------------------+
| id | select_type | table | type | possible_keys | key    | key_len | ref   | rows | Extra                    |
+----+-------------+-------+------+---------------+--------+---------+-------+------+--------------------------+
|  1 | SIMPLE      | mf    | ref  | gender        | gender | 2       | const |   36 | Using where; Using index |
+----+-------------+-------+------+---------------+--------+---------+-------+------+--------------------------+
1 row in set (0.00 sec)

mysql> EXPLAIN SELECT id FROM mf WHERE gender='F';
+----+-------------+-------+------+---------------+--------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys | key    | key_len | ref   | rows | Extra       |
+----+-------------+-------+------+---------------+--------+---------+-------+------+-------------+
|  1 | SIMPLE      | mf    | ref  | gender        | gender | 2       | const |    3 | Using where |
+----+-------------+-------+------+---------------+--------+---------+-------+------+-------------+
1 row in set (0.00 sec)

mysql> EXPLAIN SELECT id FROM mf WHERE gender='M';
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | mf    | ALL  | gender        | NULL | NULL    | NULL |   40 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)

mysql>

InnoDB के लिए विश्लेषण

जब डेटा को InnoDB के रूप में लोड किया गया था, तो कृपया ध्यान दें कि सभी चार EXPLAINयोजनाओं में genderसूचकांक का उपयोग किया गया था । तीसरी और चौथी EXPLAINयोजनाओं में genderसूचकांक का उपयोग किया गया था, भले ही अनुरोधित डेटा था id। क्यों? क्योंकि idमें है PRIMARY KEYऔर सभी माध्यमिक अनुक्रमों में संदर्भ बिंदुPRIMARY KEY ( gen_clust_index के माध्यम से ) वापस आ गए हैं ।

MyISAM के लिए विश्लेषण

जब डेटा को MyISAM के रूप में लोड किया गया था, तो कृपया ध्यान दें कि पहले तीन EXPLAINयोजनाओं में genderसूचकांक का उपयोग किया गया था । चौथी EXPLAINयोजना में, क्वेरी ऑप्टिमाइज़र ने एक सूचकांक का उपयोग नहीं करने का निर्णय लिया। इसने इसके बजाय एक पूर्ण तालिका स्कैन का विकल्प चुना। क्यों?

DBMS की परवाह किए बिना, क्वेरी ऑप्टिमाइज़र एक बहुत ही सरल नियम-पर-अंगूठे पर काम करते हैं: यदि कोई इंडेक्स लुकअप करने के लिए उपयोग किए जाने वाले उम्मीदवार के रूप में प्रदर्शित किया जाता है और क्वेरी ऑप्टिमाइज़र गणना करता है कि उसे कुल संख्या का 5% से अधिक लुकअप करना होगा तालिका में पंक्तियाँ:

  • यदि पूर्ण पुनर्प्राप्ति के लिए सभी आवश्यक कॉलम चयनित सूचकांक में हैं, तो एक पूर्ण सूचकांक स्कैन किया जाता है
  • एक पूर्ण तालिका स्कैन अन्यथा

निष्कर्ष

यदि आपके पास उचित कवरिंग इंडेक्स नहीं हैं, या यदि किसी दिए गए टपल के लिए प्रमुख जनसंख्या तालिका का 5% से अधिक है, तो छह चीजें होनी चाहिए:

  1. इस अहसास के लिए आइए कि आपको प्रश्नों को प्रोफाइल करना होगा
  2. सभी का पता लगाएं WHERE, GROUP BYऔर आदेश BY` उन प्रश्नों से खंड
  3. इस क्रम में अनुक्रमित करें
    • WHERE स्थैतिक मूल्यों के साथ खंड कॉलम
    • GROUP BY कॉलम
    • ORDER BY कॉलम
  4. पूर्ण तालिका स्कैन से बचें (एक समझदार WHEREखंड का अभाव )
  5. खराब कुंजी आबादी से बचें (या उन खराब कुंजी आबादी को कम से कम कैश करें)
  6. टेबल्स के लिए सबसे अच्छा MySQL स्टोरेज इंजन ( InnoDB या MyISAM ) तय करें

मैंने अतीत में अंगूठे के इस 5% नियम के बारे में लिखा है:

UPDATE 2012-11-14 13:05 EDT

मैंने आपके प्रश्न पर और मूल SO पोस्ट पर एक नज़र डाला । फिर, मैंने Analysis for InnoDBपहले अपने उल्लेख के बारे में सोचा । यह personतालिका के साथ मेल खाता है । क्यों?

दोनों तालिकाओं के लिए mfऔरperson

  • भंडारण इंजन InnoDB है
  • प्राथमिक कुंजी है id
  • तालिका का उपयोग द्वितीयक सूचकांक द्वारा होता है
  • यदि तालिका MyISAM थी, तो हम एक पूरी तरह से अलग EXPLAINयोजना देखेंगे

अब, SO प्रश्न से क्वेरी को देखें select * from person order by age\G:। चूंकि कोई WHEREखंड नहीं है, इसलिए आपने स्पष्ट रूप से एक पूर्ण तालिका स्कैन की मांग की है । तालिका का डिफ़ॉल्ट क्रम क्रमांक (id PRIMARY KEY) होगा क्योंकि इसका स्वत: स्वरूप और gen_clust_index (उर्फ क्लस्टर इंडेक्स) आंतरिक पंक्ति द्वारा आदेशित है । जब आप सूचकांक द्वारा आदेश देते हैं, तो ध्यान रखें कि InnoDB द्वितीयक सूचकांक में प्रत्येक अनुक्रमणिका प्रविष्टि से जुड़ी हुई पंक्ति होती है। यह हर बार पूर्ण पंक्ति पहुंच की आंतरिक आवश्यकता का उत्पादन करता है।

ORDER BYयदि आप InnoDB अनुक्रमणिका को व्यवस्थित करने के तरीके के बारे में इन तथ्यों को अनदेखा करते हैं, तो एक InnoDB टेबल पर सेट करना एक कठिन काम हो सकता है।

उस SO क्वेरी पर वापस जा रहे हैं, जब से आपने स्पष्ट रूप से एक पूर्ण तालिका स्कैन की मांग की थी , IMHO MySQL क्वेरी ऑप्टिमाइज़र ने सही काम किया (या कम से कम, कम से कम प्रतिरोध का रास्ता चुना)। जब यह InnoDB और SO क्वेरी की बात आती है, तो पूर्ण तालिका स्कैन करना और फिर filesortपूर्ण अनुक्रमणिका स्कैन करने के बजाय कुछ करना और प्रत्येक द्वितीयक अनुक्रमणिका प्रविष्टि के लिए gen_clust_index के माध्यम से पंक्ति लुकअप करना आसान होता है।

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

अद्यतन 2012-11-14 14:21 EDT

अंडरस्टैंडिंग माईक्यूएक्स इंटर्नल बुक के अनुसार

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

पृष्ठ 202 अनुच्छेद 7 निम्नलिखित कहता है:

डेटा को एक विशेष संरचना में संग्रहीत किया जाता है जिसे क्लस्टर्ड इंडेक्स कहा जाता है , जो कि मुख्य मूल्य के रूप में प्राथमिक कुंजी अभिनय के साथ बी-ट्री है, और डेटा भाग में वास्तविक रिकॉर्ड (एक संकेतक के बजाय) है। इस प्रकार, प्रत्येक InnoDB तालिका में एक प्राथमिक कुंजी होनी चाहिए। यदि किसी को आपूर्ति नहीं की जाती है, तो एक विशेष पंक्ति आईडी स्तंभ जो सामान्य रूप से उपयोगकर्ता को दिखाई नहीं देता है, प्राथमिक कुंजी के रूप में कार्य करने के लिए जोड़ा जाता है। द्वितीयक कुंजी प्राथमिक कुंजी का मान संग्रहीत करेगी जो रिकॉर्ड की पहचान करती है। बी-ट्री कोड innobase / btr / btr0btr.c में पाया जा सकता है ।

यही कारण है कि मैंने पहले कहा था: एक पूर्ण अनुक्रमणिका स्कैन और प्रत्येक द्वितीयक अनुक्रमणिका प्रविष्टि के लिए gen_clust_index के माध्यम से पंक्ति लुकअप करने के बजाय कुछ पूर्ण तालिका स्कैन करना अधिक आसान है । InnoDB हर बार एक डबल इंडेक्स लुकअप करने जा रहा है । यह एक तरह का क्रूर लगता है, लेकिन यह सिर्फ तथ्य है। फिर, WHEREक्लॉज की कमी को ध्यान में रखें । यह, अपने आप में, एक पूर्ण तालिका स्कैन करने के लिए MySQL क्वेरी ऑप्टिमाइज़र का संकेत है।


रोलांडो, इस तरह के एक विस्तृत और विस्तृत जवाब के लिए धन्यवाद। हालांकि, यह अनुक्रमित FOR ORDER BY(जो इस प्रश्न में विशिष्ट मामला है) का चयन करने के लिए प्रासंगिक प्रतीत नहीं होता है । प्रश्न में कहा गया था कि इस मामले में भंडारण इंजन था InnoDB(और मूल एसओ सवाल दिखाता है कि 10k पंक्तियां समान रूप से 8 वस्तुओं में वितरित की जाती हैं, कार्डिनैलिटी यहां भी एक मुद्दा नहीं होनी चाहिए)। अफसोस की बात है, मुझे नहीं लगता कि यह सवाल का जवाब देता है।
ईगलजी

यह दिलचस्प है, क्योंकि पहला भाग मेरी पहली वृत्ति के साथ-साथ था (इसमें अच्छी कार्डिनैलिटी नहीं थी इसलिए mysql ने फुल स्कैन का उपयोग करना चुना)। लेकिन जितना मैंने पढ़ा, वह नियम अनुकूलन द्वारा आदेश के लिए लागू नहीं हुआ। क्या आप सुनिश्चित हैं कि यह निर्दोष क्लस्टर इंडेक्स के लिए प्राथमिक कुंजी द्वारा आदेश है? यह पोस्ट इंगित करता है कि प्राथमिक कुंजी अंत में जुड़ जाती है, इसलिए क्या यह अनुक्रमांक के स्पष्ट कॉलम (ओं) पर अभी भी नहीं होगा? संक्षेप में, मैं अभी भी स्टम्प्ड हूँ!
डेरेक डाउनी

1
filesortचयन एक सरल कारण के लिए क्वेरी अनुकूलक द्वारा पर निर्णय लिया गया था: यह डेटा है कि आप के पूर्वज्ञान का अभाव है। यदि आपकी पसंद सूचकांक संकेत का उपयोग करने के लिए है (अंक # 2 के आधार पर) आपको चलने के समय को संतोषजनक बनाता है, तो हर तरह से, इसके लिए जाएं। मैंने जो उत्तर दिया, वह यह दिखाने के लिए एक अकादमिक अभ्यास था कि कैसे MySQL क्वेरी ऑप्टिमाइज़र के रूप में अच्छी तरह से कार्रवाई के पाठ्यक्रम का सुझाव दिया जा सकता है।
रोलैंडमाइसीडीडीबीए

1
मैंने इसे और अन्य पोस्टों के माध्यम से पढ़ा और फिर से पढ़ा है, और मैं केवल इस बात से सहमत हो सकता हूं कि यह प्राथमिक कुंजी पर निर्दोष आदेश के साथ करना है क्योंकि हम सभी का चयन कर रहे हैं (और एक कवरिंग इंडेक्स नहीं)। मुझे आश्चर्य है कि ORDER BY अनुकूलन दस्तावेज़ पृष्ठ में इस InnoDB-विशिष्ट विषमता का कोई उल्लेख नहीं है। वैसे भी, रोलैंडो को +1
डेरेक डाउनी

1
@eggyal यह इस सप्ताह लिखा गया था। अगर डेटा मेमोरी में फिट नहीं होता है, तो उसी एक्सप्लेन प्लान और फुल स्कैन में अधिक समय लगता है।
डेरेक डाउनी

0

एसओ पर एक और सवाल पर डेनिस के जवाब से अनुकूलित (अनुमति के साथ) :

चूंकि सभी रिकॉर्ड (या लगभग सभी) क्वेरी द्वारा प्राप्त किए जाएंगे, इसलिए आप आमतौर पर बिना किसी इंडेक्स के बेहतर होते हैं। इसका कारण यह है, यह वास्तव में एक सूचकांक को पढ़ने के लिए कुछ खर्च करता है।

जैसा कि आप पूरी तालिका के लिए जा रहे हैं, क्रमिक रूप से तालिका पढ़ रहे हैं और इसकी पंक्तियों को स्मृति में सॉर्ट करना आपकी सबसे सस्ती योजना हो सकती है। यदि आपको केवल कुछ पंक्तियों की आवश्यकता है और सबसे अधिक जहां क्लॉज का मिलान होगा, तो सबसे छोटे इंडेक्स के लिए जाना ट्रिक का काम करेगा।

यह समझने के लिए कि डिस्क I / O को शामिल क्यों करें।

मान लीजिए कि आप एक सूचकांक के बिना पूरी तालिका चाहते हैं। ऐसा करने के लिए, आप तालिका में अंत तक पहुँचने तक, क्रम में शामिल विभिन्न डिस्क पृष्ठों पर जाकर data_page1, data_page2, data_page3 आदि पढ़ते हैं। आप तब छाँटकर लौट आते हैं।

यदि आप एक सूचकांक के बिना शीर्ष 5 पंक्तियों को चाहते हैं, तो आप क्रमिक रूप से शीर्ष 5 पंक्तियों को छांटते हुए, पूरी तालिका को पहले की तरह पढ़ेंगे। कुल मिलाकर, यह बहुत सी पंक्तियों के लिए पढ़ना और छांटना है।

मान लीजिए, अब, कि आप एक सूचकांक के साथ पूरी तालिका चाहते हैं। ऐसा करने के लिए, आप अनुक्रमिक रूप से index_page1, index_page2, आदि पढ़ते हैं। इसके बाद आपको डेटा कहा जाता है, कहते हैं, data_page3, फिर data_page1, फिर data_page3, फिर data_page2, आदि, एक पूरी तरह से यादृच्छिक क्रम में (जिससे डेटा में छंटनी पंक्तियाँ प्रकट होती हैं)। इसमें शामिल IO इसे पूरी तरह से पूरी तरह से पढ़ने के लिए सस्ता बनाता है और मेमोरी में ग्रैब बैग को सॉर्ट करता है।

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

एक अच्छा SQL क्वेरी प्लानर, btw, इस बारे में अपना निर्णय करेगा कि किसी इंडेक्स का उपयोग करना है या नहीं कि आपका डेटा कितना खंडित है या नहीं। यदि क्रम में पंक्तियों को लाने का मतलब है कि तालिका में आगे और पीछे ज़ूम करना, तो एक अच्छा योजनाकार यह तय कर सकता है कि यह सूचकांक का उपयोग करने के लायक नहीं है। इसके विपरीत, यदि तालिका को उसी सूचकांक का उपयोग करके क्लस्टर किया जाता है, तो पंक्तियों को क्रम में रहने की गारंटी दी जाती है, जिससे यह संभावना बढ़ जाती है कि इसका उपयोग हो जाएगा।

लेकिन फिर, यदि आप उसी क्वेरी को किसी अन्य तालिका के साथ जोड़ते हैं और उस अन्य तालिका में एक अत्यंत चयनात्मक होता है जहां क्लॉज जो एक छोटे सूचकांक का उपयोग कर सकता है, तो योजनाकार यह तय कर सकता है कि यह वास्तव में बेहतर है, जैसे कि सभी पंक्तियों की आईडी foo, जो हैश के रूप में टैग की गई हैं तालिकाओं में शामिल हों, और उन्हें स्मृति में क्रमबद्ध करें।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.