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

mysql:rất đơn giản SELECT id id ORDER BY LIMIT sẽ không sử dụng INDEX như mong đợi (?!)

Tra cứu chỉ mục theo giá trị , không theo vị trí . Một chỉ mục có thể tìm kiếm giá trị 2955900, nhưng bạn không yêu cầu điều đó. Bạn đang yêu cầu truy vấn bắt đầu ở độ lệch của hàng thứ 2955900 trong bảng.

Trình tối ưu hóa không thể giả định rằng tất cả các giá trị khóa chính là liên tiếp. Vì vậy, rất có thể hàng thứ 2955900 có giá trị cao hơn nhiều.

Ngay cả khi các giá trị khóa chính liên tiếp nhau, bạn có thể có điều kiện WHERE chỉ khớp, ví dụ:45% số hàng. Trong trường hợp đó, giá trị id trên hàng thứ 2955900 sẽ là cách quá giá trị id 2955900.

Nói cách khác, tra cứu chỉ mục của giá trị id 2955900 sẽ không phân phối hàng thứ 2955900.

Vì vậy, MySQL không thể sử dụng chỉ mục cho phần bù của giới hạn. Nó phải quét các hàng để đếm chúng cho đến khi nó đạt đến hàng bù + hàng giới hạn.

MySQL có tối ưu hóa liên quan đến LIMIT , nhưng đó là việc dừng quét bảng khi nó đã đạt đến số hàng để trả về. Trình tối ưu hóa vẫn có thể báo cáo trong một kế hoạch GIẢI THÍCH mà nó mong đợi có thể phải quét toàn bộ bảng.

Một sự hiểu lầm thường xuyên về FORCE INDEX là nó buộc sử dụng một chỉ mục. :-) Trong thực tế, nếu truy vấn không thể sử dụng một chỉ mục (hoặc nếu các chỉ mục có sẵn không có bất kỳ lợi ích nào cho truy vấn này), FORCE INDEX không có hiệu lực.

Nhận xét lại của bạn:

Phân trang là một vấn đề thường gặp của các ứng dụng web theo hướng dữ liệu. Mặc dù tính năng này phổ biến như thế nào, nhưng không dễ để tối ưu hóa. Dưới đây là một số mẹo:

  • Tại sao bạn lại truy vấn với offset 2955900? Bạn có thực sự mong đợi người dùng sẽ xem qua nhiều trang đó không? Hầu hết người dùng bỏ cuộc sau một vài trang (chính xác là bao nhiêu tùy thuộc vào loại ứng dụng và dữ liệu).

  • Giảm số lượng truy vấn. Chức năng phân trang của bạn có thể tìm nạp 5-10 trang đầu tiên, ngay cả khi chỉ nó hiển thị trang đầu tiên cho người dùng. Lưu vào bộ nhớ đệm các trang khác, với giả định rằng người dùng sẽ xem qua một vài trang. Chỉ khi chúng vượt qua nhóm trang được lưu trong bộ nhớ cache thì ứng dụng của bạn mới phải thực hiện một truy vấn khác. Bạn thậm chí có thể lưu vào bộ đệm tất cả 10 trang trong Javascript trên trình duyệt của khách hàng để nhấp vào "Tiếp theo" là ngay lập tức cho họ (ít nhất là cho một vài trang đầu tiên).

  • Đừng đặt nút "Cuối cùng" trên bất kỳ giao diện người dùng nào, vì mọi người sẽ nhấp vào nó vì tò mò. Lưu ý rằng Google có nút "Tiếp theo" nhưng không có nút "Cuối cùng". Vì vậy, bản thân giao diện người dùng không khuyến khích mọi người chạy các truy vấn không hiệu quả với hiệu số cao.

  • Nếu người dùng đang xem xét từng trang một, hãy sử dụng giá trị id cao nhất được trả về ở trang trước trong mệnh đề WHERE của truy vấn trang tiếp theo. I E. sau đây không sử dụng chỉ mục, ngay cả khi không có gợi ý FORCE INDEX:

    SELECT * FROM thistable WHERE id > 544 LIMIT 20
    



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Hướng dẫn Sao lưu và Khôi phục (Xuất và Nhập) Cơ sở dữ liệu MySQL

  2. Laravel - cách cập nhật toàn bộ bộ sưu tập

  3. SQL để tạo bảng ma trận

  4. Cách đặt innodb làm công cụ mặc định

  5. Ngày và giờ gần nhất tiếp theo trong MySQL