Mysql
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Mysql

Khóa chính MySQL đã có trong một số loại thứ tự mặc định chưa

Câu trả lời ngắn gọn là có, khóa chính có thứ tự, tất cả các chỉ mục đều có thứ tự và khóa chính chỉ đơn giản là một chỉ mục duy nhất.

Như bạn đã nói đúng, bạn không nên dựa vào dữ liệu được trả về theo thứ tự dữ liệu được lưu trữ, trình tối ưu hóa có thể trả lại nó theo bất kỳ thứ tự nào mà nó thích và điều này sẽ phụ thuộc vào kế hoạch truy vấn. Tuy nhiên, tôi sẽ cố gắng giải thích tại sao truy vấn của bạn đã hoạt động trong 12 năm.

Chỉ mục phân cụm của bạn chỉ là dữ liệu bảng của bạn và khóa phân cụm của bạn xác định thứ tự mà nó được lưu trữ. Dữ liệu được lưu trữ trên lá và khóa phân cụm giúp gốc (và các ghi chú trung gian) hoạt động như con trỏ để nhanh chóng truy cập lá bên phải để lấy dữ liệu. Chỉ mục không phân nhóm là một cấu trúc rất giống nhau, nhưng mức thấp nhất chỉ đơn giản là chứa một con trỏ đến vị trí chính xác trên lá của chỉ mục được phân nhóm.

Trong MySQL, khóa chính và chỉ mục được phân cụm là đồng nghĩa với nhau, vì vậy khóa chính được sắp xếp theo thứ tự, tuy nhiên về cơ bản chúng là hai thứ khác nhau. Trong các DBMS khác, bạn có thể xác định cả khóa chính và chỉ mục theo nhóm, khi bạn làm điều này, khóa chính của bạn sẽ trở thành một chỉ mục không hợp nhất duy nhất với một con trỏ quay lại chỉ mục được phân nhóm.

Nói một cách đơn giản nhất, bạn có thể tưởng tượng một bảng có cột ID là khóa chính và một cột khác (A), cấu trúc B-Tree cho chỉ mục nhóm của bạn sẽ giống như sau:

Root Node
                                +---+
                                | 1 |
                                +---+
Intermediate Nodes

                    +---+       +---+       +---+
                    | 1 |       | 4 |       | 7 |
                    +---+       +---+       +---+

Leaf
            +-----------+   +-----------+   +-----------+
    ID ->   | 1 | 2 | 3 |   | 4 | 5 | 6 |   | 7 | 8 | 9 |
    A ->    | A | B | C |   | D | E | F |   | G | H | I |
            +-----------+   +-----------+   +-----------+

Trong thực tế, các trang lá sẽ lớn hơn nhiều, nhưng đây chỉ là bản demo. Mỗi trang cũng có một con trỏ đến trang tiếp theo và trang trước đó để dễ dàng xem qua cây. Vì vậy, khi bạn thực hiện một truy vấn như:

SELECT ID, A
FROM T
WHERE ID > 5
LIMIT 1;

bạn đang quét một chỉ mục duy nhất nên rất có thể đây sẽ là một quá trình quét tuần tự. Rất có thể không được đảm bảo.

MySQL sẽ quét nút gốc, nếu có khả năng khớp, nó sẽ chuyển sang các nút trung gian, nếu mệnh đề là WHERE ID < 0 thì MySQL sẽ biết rằng không có kết quả nào nếu không đi xa hơn nút gốc.

Khi nó chuyển sang nút trung gian, nó có thể xác định rằng nó cần bắt đầu trên trang thứ hai (từ 4 đến 7) để bắt đầu tìm kiếm ID > 5 . Vì vậy, nó sẽ tuần tự quét lá bắt đầu từ trang thứ hai, khi đã xác định được LIMIT 1 nó sẽ dừng lại khi nó tìm thấy một kết quả phù hợp (trong trường hợp này là 6) và trả về dữ liệu này từ lá. Trong một ví dụ đơn giản như vậy, hành vi này có vẻ đáng tin cậy và hợp lý. Tôi đã cố gắng ép buộc các trường hợp ngoại lệ bằng cách chọn một giá trị ID mà tôi biết là ở cuối trang lá để xem lá có được quét theo thứ tự ngược lại hay không, nhưng vẫn chưa thể tạo ra hành vi này, tuy nhiên điều này không có nghĩa nó sẽ không xảy ra hoặc các bản phát hành trong tương lai của MySQL sẽ không thực hiện điều này trong các tình huống tôi đã thử nghiệm.

Trong ngắn hạn, chỉ cần thêm một đơn đặt hàng bằng hoặc sử dụng MIN (ID) và được thực hiện với nó. Tôi sẽ không mất quá nhiều thời gian khi cố gắng nghiên cứu kỹ hoạt động bên trong của trình tối ưu hóa truy vấn để xem loại phân mảnh nào hoặc các phạm vi dữ liệu sẽ được yêu cầu để quan sát thứ tự khác nhau của chỉ mục được nhóm trong kế hoạch truy vấn.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Thêm 1 vào một trường

  2. Tìm điểm trong đa giác PHP

  3. Lấy các ký tự đặc biệt ra khỏi cơ sở dữ liệu MySQL với PHP

  4. php mysql PDO gặp lỗi nghiêm trọng khi gọi 2 hàm để chạy câu lệnh sql trong cùng một tệp

  5. Laravel 4:Nơi không tồn tại