ดัชนีต้องครอบคลุมคอลัมน์ที่เลือกทั้งหมดเพื่อให้ ORDER BY ใช้หรือไม่


15

เมื่อเร็ว ๆ นี้ที่บางคนถามว่าทำไมไม่สั่งโดยใช้ดัชนี?

สถานการณ์เกี่ยวข้องกับตาราง InnoDB อย่างง่ายใน MySQL ประกอบด้วยสามคอลัมน์และ 10k แถว หนึ่งในคอลัมน์เป็นจำนวนเต็มถูกทำดัชนี - และ OP พยายามดึงตารางทั้งหมดของเขาที่เรียงลำดับในคอลัมน์นั้น:

SELECT * FROM person ORDER BY age

เขาแนบEXPLAINเอาท์พุทแสดงว่าแบบสอบถามนี้ได้รับการแก้ไขด้วยfilesort(แทนที่จะเป็นดัชนี) และถามว่าทำไมจึงเป็นเช่นนั้น

แม้จะมีคำใบ้ FORCE INDEX FOR ORDER BY (age) ที่ก่อให้เกิดดัชนีที่จะใช้ , คนตอบ (กับการสนับสนุนความเห็น / upvotes จากคนอื่น ๆ ) ว่าดัชนีจะใช้เฉพาะสำหรับการเรียงลำดับเมื่อคอลัมน์ที่เลือกจะอ่านทั้งหมดจากดัชนี (เช่นเป็นปกติจะระบุโดยUsing indexในExtraคอลัมน์ ของEXPLAINเอาท์พุท) คำอธิบายที่ได้รับในภายหลังว่าภายในดัชนีแล้วเรียกคอลัมน์จากผลตารางในการสุ่ม I / O filesortซึ่งมุมมองที่เป็นราคาแพงกว่า

สิ่งนี้ดูเหมือนจะปรากฏในหน้าของบทที่เกี่ยวกับORDER BYการปรับให้เหมาะสมซึ่งไม่เพียง แต่บ่งบอกถึงความประทับใจที่น่าพึงพอใจORDER BYที่ดัชนีพอใจมากกว่าการเรียงลำดับเพิ่มเติม (แน่นอนfilesortคือการรวมกันของ quicksort และการรวมและดังนั้นจึง ต้องมีขอบเขตล่างในขณะที่เดินผ่านดัชนีตามลำดับและมองเข้าไปในตารางควรจะเป็นเช่นนี้ก็สมเหตุสมผลดี) แต่ก็ไม่ควรพูดถึง "การเพิ่มประสิทธิภาพ" ที่ถูกกล่าวหาในขณะนี้เช่นกัน:Ω(nlog n)O(n)

แบบสอบถามต่อไปนี้ใช้ดัชนีเพื่อแก้ไขORDER BYส่วน:

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

สำหรับการอ่านของฉันนั่นเป็นกรณีในสถานการณ์นี้อย่างแม่นยำ (แต่ดัชนีไม่ได้ถูกใช้โดยไม่มีคำใบ้อย่างชัดเจน)

คำถามของฉันคือ:

  • จำเป็นหรือไม่ที่ทุกคอลัมน์ที่เลือกต้องถูกจัดทำดัชนีเพื่อให้ MySQL เลือกใช้ดัชนี?

    • ถ้าใช่เอกสารนี้อยู่ที่ไหน (ถ้าเลย)

    • ถ้าไม่เกิดอะไรขึ้นที่นี่

คำตอบ:


14

จำเป็นหรือไม่ที่ทุกคอลัมน์ที่เลือกต้องถูกจัดทำดัชนีเพื่อให้ MySQL เลือกใช้ดัชนี?

นี่เป็นคำถามที่โหลดเพราะมีปัจจัยที่กำหนดว่าดัชนีคุ้มค่าหรือไม่

ปัจจัย # 1

สำหรับดัชนีใด ๆ ประชากรหลักคืออะไร กล่าวอีกนัยหนึ่ง cardinality (จำนวนที่แตกต่าง) ของสิ่งอันดับทั้งหมดที่บันทึกในดัชนีคืออะไร?

ปัจจัย # 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>

ทดสอบ MyISAM

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. หลีกเลี่ยง Bad Key Populations (หรืออย่างน้อยแคชประชากร Bad Key เหล่านั้น)
  6. ตัดสินใจเลือก MySQL Storage Engine ที่ดีที่สุด ( InnoDBหรือMyISAM ) สำหรับ Tables

ฉันได้เขียนเกี่ยวกับกฎ 5% ของหัวแม่มือในอดีตที่ผ่านมา:

อัพเดท 2012-11-14 13:05 EDT

ผมเอากลับมาดูที่คำถามของคุณและในการโพสต์ SO เดิม จากนั้นฉันก็คิดถึงสิ่งที่Analysis for InnoDBฉันพูดถึงก่อนหน้านี้ มันตรงกับpersonตาราง ทำไม?

สำหรับทั้งโต๊ะmfและperson

  • Storage Engine คือ InnoDB
  • คีย์หลักคือ id
  • การเข้าถึงตารางโดยดัชนีรอง
  • ถ้าตารางคือ MyISAM เราจะเห็นEXPLAINแผนแตกต่างอย่างสิ้นเชิง

ตอนนี้มองไปที่การสอบถามจากคำถาม SO select * from person order by age\Gนี้: เนื่องจากไม่มีWHEREข้อคุณอย่างชัดเจนเรียกร้องตารางการสแกนเต็มรูปแบบ การเรียงลำดับเริ่มต้นของตารางจะเป็นโดยid(คีย์หลัก) เพราะ auto_increment และของgen_clust_index (aka ดัชนีคลัสเตอร์) ได้รับคำสั่งจาก ROWID เมื่อคุณเรียงลำดับตามดัชนีโปรดจำไว้ว่าดัชนีรอง InnoDB มีการแนบแถวเข้ากับรายการดัชนีแต่ละรายการ สิ่งนี้สร้างความต้องการภายในสำหรับการเข้าถึงแถวเต็มทุกครั้ง

การตั้งค่าORDER BYบนตาราง InnoDB อาจเป็นงานที่ค่อนข้างยุ่งยากหากคุณไม่สนใจข้อเท็จจริงเหล่านี้เกี่ยวกับวิธีการจัดเรียงดัชนี InnoDB

กลับไปที่คำสั่ง SO นั้นเนื่องจากคุณต้องการสแกนแบบเต็มตาราง IMHO the MySQL Query Optimizer ทำสิ่งที่ถูกต้อง (หรืออย่างน้อยเลือกเส้นทางที่มีความต้านทานน้อยที่สุด) เมื่อพูดถึง InnoDB และการสืบค้น SO มันง่ายกว่ามากที่จะทำการสแกนตารางแบบเต็มรูปแบบและบางส่วนfilesortแทนที่จะทำการสแกนดัชนีแบบเต็มและการค้นหาแถวผ่าน gen_clust_index สำหรับรายการดัชนีรองแต่ละรายการ

ฉันไม่ได้เป็นผู้สนับสนุนการใช้ดัชนีคำแนะนำเพราะมันละเว้นแผนอธิบาย อย่างไรก็ตามหากคุณรู้จักข้อมูลของคุณดีกว่า InnoDB จริงๆคุณจะต้องหันไปใช้ดัชนีคำแนะนำโดยเฉพาะอย่างยิ่งกับข้อความค้นหาที่ไม่มีWHEREส่วนคำสั่ง

อัพเดท 2012-11-14 14:21 EDT

ตามหนังสือเข้าใจ MySQL ภายใน

ป้อนคำอธิบายรูปภาพที่นี่

หน้า 202 ย่อหน้า 7 พูดว่าต่อไปนี้:

ข้อมูลถูกเก็บไว้ในโครงสร้างพิเศษที่เรียกว่าดัชนีคลัสเตอร์ซึ่งเป็นต้นไม้ B ที่มีคีย์หลักทำหน้าที่เป็นค่าคีย์และบันทึกจริง (แทนที่จะเป็นตัวชี้) ในส่วนข้อมูล ดังนั้นแต่ละตาราง InnoDB จะต้องมีคีย์หลัก หากไม่มีการระบุจะไม่มีการเพิ่มคอลัมน์ ID แถวพิเศษที่ผู้ใช้ไม่สามารถมองเห็นได้เพื่อทำหน้าที่เป็นคีย์หลัก คีย์รองจะเก็บค่าของคีย์หลักที่ระบุระเบียน รหัส B ต้นไม้สามารถพบได้ในinnobase / BTR / btr0btr.c

นี่คือเหตุผลที่ผมกล่าวก่อนหน้านี้: มันอยู่ไกลง่ายต่อการดำเนินการตารางการสแกนเต็มรูปแบบแล้ว filesort บางมากกว่าการทำดัชนีสแกนเต็มรูปแบบและการค้นหาแถวผ่าน gen_clust_index สำหรับรายการดัชนีแต่ละรอง InnoDB จะไปทำดัชนีการค้นหาคู่ทุกครั้ง นั่นฟังดูโหดร้าย แต่นั่นเป็นเพียงข้อเท็จจริง อีกครั้งคำนึงถึงการขาดWHEREประโยค ในตัวมันเองนั้นเป็นคำใบ้ของ MySQL Query Optimizer ที่จะทำการสแกนเต็มตาราง


Rolando ขอขอบคุณสำหรับคำตอบอย่างละเอียดและละเอียด อย่างไรก็ตามดูเหมือนว่าจะไม่เกี่ยวข้องกับการเลือกดัชนีFOR ORDER BY(ซึ่งเป็นกรณีเฉพาะในคำถามนี้) คำถามนี้ระบุว่าในกรณีนี้เครื่องมือจัดเก็บข้อมูลเป็นInnoDB(และคำถาม SO ดั้งเดิมแสดงให้เห็นว่าแถว 10k มีการกระจายอย่างเท่าเทียมกันใน 8 รายการความเป็นเชิงการนับไม่ควรเป็นปัญหาเช่นกัน) น่าเศร้าที่ฉันไม่คิดว่านี่เป็นคำตอบของคำถาม
eggyal

นี่เป็นเรื่องที่น่าสนใจเนื่องจากส่วนแรกเป็นสัญชาตญาณแรกของฉันเช่นกัน (มันไม่มีความสำคัญทางหัวใจที่ดีดังนั้น mysql จึงเลือกใช้การสแกนแบบเต็ม) แต่ยิ่งฉันอ่านมากขึ้นกฎนั้นก็ไม่ได้ดูเหมือนจะใช้สำหรับการสั่งซื้อโดยการเพิ่มประสิทธิภาพ คุณแน่ใจหรือว่าสั่งโดยคีย์หลักสำหรับดัชนีแบบกลุ่มของ Innodb? โพสต์นี้ระบุว่ามีการเพิ่มคีย์หลักในตอนท้ายดังนั้นการเรียงลำดับจะยังคงอยู่ในคอลัมน์ที่ชัดเจนของดัชนีหรือไม่ ในระยะสั้นฉันยังคงนิ่งงัน!
Derek Downey

1
ตัวfilesortเลือก Query Optimizer ได้รับการตัดสินด้วยเหตุผลง่ายๆหนึ่งข้อ: มันขาดความรู้ล่วงหน้าเกี่ยวกับข้อมูลที่คุณมี หากคุณเลือกที่จะใช้คำแนะนำดัชนี (ตามปัญหา # 2) จะทำให้คุณพึงพอใจกับเวลาที่ใช้งานให้ลองทำตามนั้น คำตอบที่ฉันให้ไว้เป็นเพียงแบบฝึกหัดทางวิชาการเพื่อแสดงให้เห็นว่า MySQL Query Optimizer สามารถสร้างอารมณ์ได้ดีเพียงใด
RolandoMySQLDBA

1
ฉันได้อ่านและอ่านโพสต์นี้และโพสต์อื่น ๆ แล้วและฉันสามารถยอมรับได้ว่าสิ่งนี้เกี่ยวข้องกับการสั่งซื้อ Innodb ในคีย์หลักเนื่องจากเราเลือกทั้งหมด (ไม่ใช่ดัชนีที่ครอบคลุม) ฉันประหลาดใจที่ไม่มีการกล่าวถึงเรื่องแปลก ๆ เฉพาะของ InnoDB ในหน้าเอกสารการเพิ่มประสิทธิภาพ ORDER BY อย่างไรก็ตาม +1 ถึง Rolando
Derek Downey

1
@eggyal นี่ถูกเขียนขึ้นในสัปดาห์นี้ สังเกตเห็นแผน EXPLAIN เดียวกันและการสแกนแบบเต็มใช้เวลานานขึ้นหากชุดข้อมูลไม่พอดีกับหน่วยความจำ
Derek Downey

0

ดัดแปลงแล้ว (ได้รับอนุญาต) จากคำตอบของ Denis สำหรับคำถามอื่นใน SO:

เนื่องจากระเบียนทั้งหมด (หรือเกือบทั้งหมด) จะถูกดึงมาจากการสืบค้นคุณมักจะดีกว่าโดยไม่มีดัชนีเลย สาเหตุของสิ่งนี้คือมีค่าใช้จ่ายในการอ่านดัชนี

ขณะที่คุณกำลังไปทั้งตารางการอ่านตารางตามลำดับและเรียงแถวในหน่วยความจำอาจเป็นแผนที่ถูกที่สุดของคุณ หากคุณต้องการเพียงไม่กี่แถวและส่วนใหญ่จะตรงกับส่วนคำสั่งที่ไปสำหรับดัชนีที่เล็กที่สุดจะทำเคล็ดลับ

เพื่อให้เข้าใจว่าเหตุใดจึงกำหนดรูปภาพ 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 จะทำการตัดสินใจว่าจะใช้ดัชนีหรือไม่ขึ้นอยู่กับว่าข้อมูลของคุณมีการแยกส่วนอย่างไร หากการเรียกแถวตามลำดับหมายถึงการซูมไปมาข้ามตารางนักวางแผนที่ดีอาจตัดสินใจว่าไม่คุ้มกับการใช้ดัชนี ในทางตรงกันข้ามหากตารางเป็นกลุ่มโดยใช้ดัชนีเดียวกันนั้นแถวจะรับประกันว่าเป็นไปตามลำดับเพิ่มโอกาสในการที่จะใช้

แต่ถ้าคุณเข้าร่วมการสืบค้นเดียวกันกับตารางอื่นและตารางอื่นนั้นมีการคัดเลือกอย่างมากซึ่งประโยคที่สามารถใช้ดัชนีขนาดเล็กได้ผู้วางแผนอาจตัดสินใจว่าจะดีกว่าจริง ๆ เช่นดึง ID ของแถวทั้งหมดที่ถูกแท็กเป็นfooแฮช เข้าร่วมตารางและเรียงลำดับพวกเขาในหน่วยความจำ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.