Thứ tự mặc định của các bản ghi cho một câu lệnh CHỌN trong MySQL là gì?


66

Giả sử bạn có bảng và dữ liệu sau:

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

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

Khi phát hành select * from t where k = 10không có order bymệnh đề, làm thế nào để MySQL sắp xếp các bản ghi theo mặc định?

Câu trả lời:


75

Đăng lại câu trả lời của tôi cho một câu hỏi tương tự liên quan đến SQL Server:

Trong thế giới SQL, thứ tự không phải là một thuộc tính vốn có của một tập hợp dữ liệu. Do đó, bạn không nhận được sự đảm bảo nào từ RDBMS rằng dữ liệu của bạn sẽ quay trở lại theo một thứ tự nhất định - hoặc thậm chí theo một thứ tự nhất quán - trừ khi bạn truy vấn dữ liệu của mình bằng mệnh đề ORDER BY.

Để trả lời câu hỏi của bạn:

  • MySQL sắp xếp các bản ghi theo cách nó muốn mà không có bất kỳ sự đảm bảo nào về tính nhất quán.
  • Nếu bạn có ý định dựa vào đơn hàng này cho bất cứ điều gì, bạn phải chỉ định đơn hàng mong muốn của mình bằng cách sử dụng ORDER BY. Để làm bất cứ điều gì khác là thiết lập cho mình những bất ngờ không mong muốn.

Đây là một thuộc tính của tất cả SQL, không chỉ MySQL. Văn bản có liên quan trong thông số SQL-92 là:

Nếu <order by mệnh đề> không được chỉ định, thì thứ tự của các hàng Q phụ thuộc vào việc triển khai.

Có các bit văn bản tương tự trong thông số kỹ thuật cho con trỏ.


26

Thứ tự của các hàng trong trường hợp không có ORDER BYmệnh đề có thể là:

  • khác nhau giữa bất kỳ hai công cụ lưu trữ;
  • nếu bạn sử dụng cùng một công cụ lưu trữ, nó có thể khác nhau giữa hai phiên bản của cùng một công cụ lưu trữ; Ví dụ ở đây , cuộn xuống "Thứ tự hàng".
  • nếu phiên bản công cụ lưu trữ giống nhau, nhưng phiên bản MySQL thì khác, nó có thể khác do trình tối ưu hóa truy vấn thay đổi giữa các phiên bản đó;
  • nếu mọi thứ đều giống nhau, nó có thể khác nhau do giai đoạn mặt trăng và điều đó là ổn.

10

Chèn là không có thứ tự, hỗn loạn, khi đến. Chỉ mục được tạo không có thứ tự trong đó các phần tử được chèn vào vị trí thích hợp trong danh sách được liên kết là chỉ mục. Hãy nghĩ về một danh sách được liên kết ba lần cho một chỉ mục, trong đó bạn có một liên kết chuyển tiếp từ một yếu tố chỉ mục này sang một liên kết tiếp theo, tìm kiếm liên kết ngược cho các mục đích truyền tải và toàn vẹn, và sau đó là một bộ con trỏ tới các bản ghi thực trong bảng phù hợp với các yếu tố được lập chỉ mục trong câu hỏi.

Dữ liệu thực tế, hỗn loạn trong lưu trữ. Chỉ số liên quan đến dữ liệu, được đặt hàng trong lưu trữ và xây dựng. Thực tế kéo dữ liệu, được đặt hàng hoặc không có thứ tự, phụ thuộc vào truy vấn liên quan.


4

Khi nói đến công cụ lưu trữ MEMOR , tôi sẽ mong đợi thứ tự theo thứ tự chèn vì bố cục chỉ mục mặc định là HASHthay vì BTREEvà không sử dụng khía cạnh nào của bố cục chỉ mục. Vì bạn đã lập chỉ mục k và k là cùng một giá trị, tất cả các khóa nhập vào cùng một nhóm băm. Vì không có lý do nào để cho rằng sự phức tạp được thêm vào để tạo ra một nhóm băm, nên thứ tự chèn có ý nghĩa nhất.

Tôi lấy cùng một bảng mẫu và dữ liệu của bạn và chạy 30 INSERTgiây và tôi đã nhận được điều này:

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>

Tôi đã quyết định thử nghiệm thêm hai giá trị khác nhau cho k: 10 và 11 Tôi đã nhận được điều này:

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>

Trông giống như thứ tự chèn. k = 11 là khóa đầu tiên được băm sau đó 10. Còn việc chèn 10 đầu tiên thay vì 11 thì sao? Đây là những gì tôi nhận được:

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>

Thật là nhất trí !!! ĐẶT HÀNG CHỨNG MINH là câu trả lời.

Sidenote về việc sử dụng các chỉ mục cho công cụ lưu trữ MEMOR

Phạm vi tìm kiếm cho NHỚ sẽ có hiệu suất tương đối khủng khiếp.

Khi tạo một chỉ mục, bạn có thể chỉ định USING BTREEmệnh đề cùng với định nghĩa của chỉ mục. Điều này sẽ cải thiện mọi thứ cho các truy vấn phạm vi.

Tìm kiếm một hàng cụ thể sẽ mang lại kết quả tương tự trong hiệu suất với HASHhoặc BTREE.

CẬP NHẬT 2011-09-22 11:18 EDT

Tôi đã học được một điều thú vị ngày hôm nay. Tôi đã đọc liên kết được cung cấp bởi @Laurynas Biveinis từ Percona: Liên kết Percona nói điều gì đó về các bảng NHỚ cho MySQL 5.5.15 :

Đặt hàng

Trong trường hợp không có ĐẶT HÀNG B, NG, các hồ sơ có thể được trả về theo thứ tự khác so với triển khai BỘ NHỚ trước đó. Đây không phải là một lỗi. Bất kỳ ứng dụng nào dựa trên một đơn đặt hàng cụ thể mà không có mệnh đề ORDER BY có thể mang lại kết quả không mong muốn. Một đơn đặt hàng cụ thể không có ORDER BY là tác dụng phụ của công cụ lưu trữ và triển khai tối ưu hóa truy vấn có thể và sẽ thay đổi giữa các bản phát hành MySQL nhỏ.

Đây là một liên kết tốt cho tôi để xem ngày hôm nay. Câu trả lời tôi đưa ra đã chứng minh rằng bảng tôi đã tải đã được truy xuất theo thứ tự tôi mong đợi HÔM NAY trong MySQL 5.5.12. Như Percona và @Laurynas Biveinis đã chỉ ra , không có gì đảm bảo trong một bản phát hành nhỏ khác.

Vì vậy, thay vì cố gắng bảo vệ câu trả lời của tôi, tôi muốn quảng bá câu trả lời từ @Laurynas Biveinis vì đây là thông tin mới nhất. Kudos và đội mũ cho @Laurynas Biveinis . Tôi cũng muốn cảm ơn @eevar vì đã lịch sự chỉ ra rằng không quảng bá các câu trả lời dành riêng cho phiên bản cho các câu hỏi. Cả hai đều nhận được upvote của tôi ngày hôm nay.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.