ลำดับเริ่มต้นของการบันทึกสำหรับคำสั่ง SELECT ใน MySQL คืออะไร?


66

สมมติว่าคุณมีตารางและข้อมูลต่อไปนี้:

create table t (
    k int,
    v int,
    index k(k)
    ) engine=memory;

insert into t (k, v)
values (10, 1),
       (10, 2),
       (10, 3);

เมื่อออกselect * from t where k = 10โดยไม่มีorder byส่วนคำสั่ง MySQL จะเรียงลำดับระเบียนตามค่าเริ่มต้นอย่างไร

คำตอบ:


75

โพสต์คำตอบของฉันใหม่สำหรับคำถามที่คล้ายกันเกี่ยวกับ SQL Server:

ในโลก SQL การสั่งซื้อไม่ใช่คุณสมบัติโดยธรรมชาติของชุดข้อมูล ดังนั้นคุณจะไม่ได้รับการรับรองจาก RDBMS ว่าข้อมูลของคุณจะกลับมาในลำดับที่แน่นอนหรือแม้กระทั่งในลำดับที่สอดคล้องกันเว้นแต่ว่าคุณจะสืบค้นข้อมูลของคุณด้วยคำสั่งย่อย ORDER BY

ดังนั้นเพื่อตอบคำถามของคุณ:

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

นี่คือคุณสมบัติของ SQL ทั้งหมดไม่ใช่แค่ MySQL ข้อความที่เกี่ยวข้องในข้อมูลจำเพาะของ SQL-92คือ:

หากไม่ได้ระบุ <order by clause> การเรียงลำดับแถวของ Q นั้นขึ้นอยู่กับการนำไปใช้งาน

มีบิตของข้อความที่คล้ายกันใน spec สำหรับเคอร์เซอร์


26

ลำดับของแถวที่ไม่มีORDER BYส่วนคำสั่งอาจเป็น:

  • แตกต่างกันระหว่างสองหน่วยเก็บข้อมูล
  • ถ้าคุณใช้เอนจินการเก็บข้อมูลเดียวกันมันอาจแตกต่างกันระหว่างเอนจิ้นการเก็บข้อมูลเดียวกันสองเวอร์ชั่น ตัวอย่างที่นี่เลื่อนลงไปที่ "ลำดับของแถว"
  • หากเวอร์ชันของเอ็นจิ้นการจัดเก็บเหมือนกัน แต่เวอร์ชั่นของ MySQL นั้นแตกต่างกันมันอาจจะแตกต่างกันเนื่องจากการเปลี่ยนแปลงของเครื่องมือเพิ่มประสิทธิภาพการสืบค้นระหว่างเวอร์ชั่นเหล่านั้น
  • ถ้าทุกอย่างเหมือนกันมันอาจแตกต่างกันเนื่องจากเฟสมูนและนั่นก็โอเค

10

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

ข้อมูลจริงวุ่นวายในการจัดเก็บ ดัชนีที่เกี่ยวข้องกับข้อมูลสั่งในการจัดเก็บและการก่อสร้าง การดึงข้อมูลจริงสั่งหรือไม่จัดลำดับขึ้นอยู่กับแบบสอบถามที่เกี่ยวข้อง


4

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

ฉันเอาตารางตัวอย่างและข้อมูลเดียวกันมาแล้วก็วิ่ง 30 วิINSERTและได้รับ:

mysql> use test
Database changed
mysql> drop table if exists t;
Query OK, 0 rows affected (0.00 sec)

mysql> create table t(k int, v int,index k(k)) engine=memory;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into t values
    -> (10, 1), (10, 2), (10, 3), (10, 1), (10, 2), (10, 3),
    -> (10, 1), (10, 2), (10, 3), (10, 1), (10, 2), (10, 3),
    -> (10, 1), (10, 2), (10, 3), (10, 1), (10, 2), (10, 3),
    -> (10, 1), (10, 2), (10, 3), (10, 1), (10, 2), (10, 3),
    -> (10, 1), (10, 2), (10, 3), (10, 1), (10, 2), (10, 3);
Query OK, 30 rows affected (0.00 sec)
Records: 30  Duplicates: 0  Warnings: 0

mysql> select * from t;
+------+------+
| k    | v    |
+------+------+
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
+------+------+
30 rows in set (0.00 sec)

mysql>

ฉันตัดสินใจทดสอบการเพิ่มค่าที่แตกต่างกันสองค่าสำหรับ k: 10 และ 11 ฉันได้รับสิ่งนี้:

mysql> use test
Database changed
mysql> drop table if exists t;
Query OK, 0 rows affected (0.02 sec)

mysql> create table t(k int, v int,index k(k)) engine=memory;
Query OK, 0 rows affected (0.01 sec)

mysql> insert into t values
    -> (11, 1), (11, 2), (11, 3), (10, 1), (10, 2), (10, 3),
    -> (11, 1), (11, 2), (11, 3), (10, 1), (10, 2), (10, 3),
    -> (10, 1), (10, 2), (10, 3), (10, 1), (10, 2), (10, 3),
    -> (10, 1), (10, 2), (10, 3), (10, 1), (10, 2), (10, 3),
    -> (10, 1), (10, 2), (10, 3), (10, 1), (10, 2), (10, 3);
Query OK, 30 rows affected (0.00 sec)
Records: 30  Duplicates: 0  Warnings: 0

mysql> select * from t;
+------+------+
| k    | v    |
+------+------+
|   11 |    1 |
|   11 |    2 |
|   11 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   11 |    1 |
|   11 |    2 |
|   11 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
+------+------+
30 rows in set (0.00 sec)

mysql>

ดูเหมือนว่าคำสั่งของการแทรก k = 11 เป็นคีย์แรกที่แฮชแล้ว 10 สิ่งที่เกี่ยวกับการแทรก 10 แรกแทน 11? นี่คือสิ่งที่ฉันได้รับ:

mysql> use test
Database changed
mysql> drop table if exists t;
Query OK, 0 rows affected (0.02 sec)

mysql> create table t(k int, v int,index k(k)) engine=memory;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into t values
    -> (10, 1), (10, 2), (10, 3), (10, 1), (10, 2), (10, 3),
    -> (11, 1), (11, 2), (11, 3), (10, 1), (10, 2), (10, 3),
    -> (11, 1), (11, 2), (11, 3), (10, 1), (10, 2), (10, 3),
    -> (10, 1), (10, 2), (10, 3), (10, 1), (10, 2), (10, 3),
    -> (10, 1), (10, 2), (10, 3), (10, 1), (10, 2), (10, 3);
Query OK, 30 rows affected (0.00 sec)
Records: 30  Duplicates: 0  Warnings: 0

mysql> select * from t;
+------+------+
| k    | v    |
+------+------+
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   11 |    1 |
|   11 |    2 |
|   11 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   11 |    1 |
|   11 |    2 |
|   11 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
+------+------+
30 rows in set (0.00 sec)

mysql>

มันเป็นเอกฉันท์ !!! คำสั่งของการแทรกคำตอบคือ

Sidenotes เกี่ยวกับการใช้ดัชนีสำหรับเครื่องมือเก็บข้อมูล MEMORY

การค้นหาย่านสำหรับหน่วยความจำจะมีประสิทธิภาพที่น่ากลัวเปรียบเทียบ

เมื่อสร้างดัชนีคุณสามารถระบุUSING BTREEข้อพร้อมกับคำจำกัดความของดัชนี สิ่งนี้จะปรับปรุงสิ่งต่าง ๆ สำหรับการสอบถามช่วง

กำลังหาแถวที่ระบุจะให้ผลเดียวกันในการทำงานกับทั้งหรือHASHBTREE

อัพเดท 2011-09-22 11:18 EDT

ฉันเรียนรู้สิ่งที่น่าสนใจในวันนี้ ฉันอ่านลิงค์ของ@Laurynas Biveinisจาก Percona: ลิงก์ Percona พูดถึงบางสิ่งเกี่ยวกับตาราง MEMORY สำหรับMySQL 5.5.15 :

การเรียงแถว

ในกรณีที่ไม่มี ORDER BY บันทึกอาจถูกส่งกลับในลำดับที่แตกต่างจากการใช้หน่วยความจำก่อนหน้า นี่ไม่ใช่ข้อผิดพลาด แอปพลิเคชันใด ๆ ที่ใช้คำสั่งซื้อที่ไม่มีคำสั่ง ORDER BY อาจส่งมอบผลลัพธ์ที่ไม่คาดคิด คำสั่งซื้อที่ไม่มี ORDER BY นั้นเป็นผลข้างเคียงของเอ็นจิ้นการจัดเก็บและการปรับใช้เคียวรีเครื่องมือเพิ่มประสิทธิภาพซึ่งอาจและจะมีการเปลี่ยนแปลงระหว่างการปล่อย MySQL เล็กน้อย

นี่เป็นลิงค์ที่ดีสำหรับฉันที่จะเห็นในวันนี้ คำตอบที่ฉันให้ไว้แสดงให้เห็นว่าตารางที่ฉันโหลดถูกดึงมาตามลำดับที่ฉันคาดหวังในวันนี้ใน MySQL 5.5.12 ดังที่ Percona และ@Laurynas Biveinisชี้ให้เห็นไม่มีการรับประกันในการปล่อยรุ่นย่อยอื่น

ดังนั้นแทนที่จะพยายามปกป้องคำตอบของฉันฉันควรส่งเสริมคำตอบจาก@Laurynas Biveinisเพราะเป็นข้อมูลล่าสุด รุ่งโรจน์และหมวกปิดสำหรับ@Laurynas Biveinis ฉันอยากจะขอบคุณ@eevarสำหรับการชี้ให้เห็นอย่างสุภาพว่าไม่ส่งเสริมคำถามคำตอบเฉพาะรุ่น พวกเขาทั้งสองได้รับการโหวตของฉันในวันนี้

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