Trình tối ưu hóa truy vấn MySQL đọc số liệu thống kê chỉ mục từ đâu?


14

Tôi đang cố gắng xác định nơi trình tối ưu hóa MySQL lấy danh sách các chỉ mục có sẵn cho một bảng khi ước tính chi phí (chuẩn bị) một truy vấn từ đó.


+1 cho câu hỏi hay này vì Nhà phát triển và DBA nên tạm dừng và suy nghĩ về cách thống kê và lưu trữ số liệu thống kê chỉ mục.
RolandoMySQLDBA

Để tham khảo, từ trang web tài liệu mysql: < dev.mysql.com/doc/refman/5.0/en/innodb-restrictions.html >> ANALYZE TABLExác định cardinality chỉ số (như được hiển thị trong cột SHOW INDEXđầu ra Cardinality ) bằng cách thực hiện tám lần lặn ngẫu nhiên cho mỗi của cây chỉ số và cập nhật ước tính cardinality chỉ số cho phù hợp. Bởi vì đây chỉ là ước tính, các lần chạy lặp lại của ANALYZE TABLE có thể tạo ra các số khác nhau. Điều này làm cho ANALYZE TABLEnhanh trên các bảng InnoDB nhưng không chính xác 100% vì nó không tính đến tất cả các hàng.
Chen Xie

Câu trả lời:


6

Câu trả lời trực tiếp cho điều này sẽ là

information_schema.statistic

mysql> desc information_schema.statistics;
+---------------+---------------+------+-----+---------+-------+
| Field         | Type          | Null | Key | Default | Extra |
+---------------+---------------+------+-----+---------+-------+
| TABLE_CATALOG | varchar(512)  | NO   |     |         |       |
| TABLE_SCHEMA  | varchar(64)   | NO   |     |         |       |
| TABLE_NAME    | varchar(64)   | NO   |     |         |       |
| NON_UNIQUE    | bigint(1)     | NO   |     | 0       |       |
| INDEX_SCHEMA  | varchar(64)   | NO   |     |         |       |
| INDEX_NAME    | varchar(64)   | NO   |     |         |       |
| SEQ_IN_INDEX  | bigint(2)     | NO   |     | 0       |       |
| COLUMN_NAME   | varchar(64)   | NO   |     |         |       |
| COLLATION     | varchar(1)    | YES  |     | NULL    |       |
| CARDINALITY   | bigint(21)    | YES  |     | NULL    |       |
| SUB_PART      | bigint(3)     | YES  |     | NULL    |       |
| PACKED        | varchar(10)   | YES  |     | NULL    |       |
| NULLABLE      | varchar(3)    | NO   |     |         |       |
| INDEX_TYPE    | varchar(16)   | NO   |     |         |       |
| COMMENT       | varchar(16)   | YES  |     | NULL    |       |
| INDEX_COMMENT | varchar(1024) | NO   |     |         |       |
+---------------+---------------+------+-----+---------+-------+
16 rows in set (0.01 sec)

Bạn có thể CHỌN từ bảng đó với

SELECT * FROM information_schema.statistics
WHERE table_schema='mydb' AND table_name='mytable';

hoặc xem số liệu thống kê bằng cách làm

HIỂN THỊ INDEXES TỪ mydb.mytable;

Xin lưu ý rằng bảng này không phải lúc nào cũng chính xác trong môi trường nặng ký. Theo định kỳ, bạn sẽ phải chạy ANALYZE TABLE đối với tất cả các bảng MyISAM được cập nhật thường xuyên. Mặt khác, Trình tối ưu hóa truy vấn MySQL, dựa trên information_schema.statistic, đôi khi có thể đưa ra các lựa chọn không tốt khi phát triển các kế hoạch EXPLAIN cho các truy vấn. Thống kê chỉ số phải được cập nhật nhất có thể.

BẢNG PHÂN TÍCH CÓ TUYỆT ĐỐI KHÔNG CÓ HIỆU QUẢ đối với các bảng InnoDB. Tất cả các số liệu thống kê chỉ mục cho InnoDB được tính toán theo yêu cầu bằng cách lặn vào các trang BTREE. Do đó, khi bạn chạy CHỈ SỐ SHOW TỪ với bảng InnoDB, các số chính được hiển thị luôn là xấp xỉ.

CẬP NHẬT 2011-06-21 12:17 EDT

Để làm rõ BẢNG ANALYZE, hãy để tôi nói lại. Chạy ANALYZE TABLE trên các bảng InnoDB là hoàn toàn vô dụng. Ngay cả khi bạn đã chạy ANALYZE TABLE trên bảng InnoDB, công cụ lưu trữ InnoDB sẽ thực hiện các lần lặn vào chỉ mục cho các xấp xỉ cardinality nhiều lần, do đó, bỏ qua các số liệu thống kê bạn vừa biên dịch . Trên thực tế, Percona đã thực hiện một số thử nghiệm trên ANALYZE TABLE và cũng đi đến kết luận đó.


5

Re: ANALYZE TABLE có TUYỆT ĐỐI KHÔNG CÓ HIỆU QUẢ đối với các bảng InnoDB.

Tôi không chắc nếu tuyên bố này là đúng. Chúng tôi đã đọc và viết rất nhiều bảng innodb và khi trình tối ưu hóa mysql đưa ra lựa chọn tồi, đầu ra giải thích của truy vấn cho thấy chiến lược tồi. và cũng hiển thị INDEXES từ bảng Innodb cho thấy rất nhiều sự khác biệt trong các giá trị cardinality của chúng. Nhưng việc chạy lệnh ANALYZE trên các bảng innodb đó sẽ khắc phục kế hoạch giải thích và cũng lấy đi hành vi phương sai của cardinality. Tôi không biết liệu lệnh bảng ANALYZE trên các bảng Innodb có giúp ích mọi lúc hay không nhưng trong trường hợp của chúng tôi, nó đã giúp khoảng 99% thời gian.

Chúng tôi đã loại bỏ hoàn toàn sự lựa chọn tồi của trình tối ưu hóa mysql bằng cách đưa "STRAIGHT_JOIN" vào các truy vấn của chúng tôi. Trình tối ưu hóa mysql này buộc không đưa ra các lựa chọn xấu hoặc bất kỳ lựa chọn nào mà chỉ tuân theo điều kiện THAM GIA của những gì chúng tôi đã xác định trong truy vấn.


Tôi đã cập nhật câu trả lời của mình để làm nổi bật sự vô dụng của BẢNG ANALYZE trên các bảng InnoDB.
RolandoMySQLDBA

Tôi đồng ý với câu trả lời của bạn khi bạn đề cập đến phương sai về số lượng. Đó chính xác là những gì tôi đã nói khi tôi nói gần đúng về tim mạch.
RolandoMySQLDBA

Tôi cũng cần đề cập rằng sử dụng gợi ý trong các truy vấn không phải lúc nào cũng là điều tốt nhất để làm khi Trình tối ưu hóa truy vấn MySQL có xu hướng loại bỏ chúng đôi khi. Đây là một liên kết đến những gì xảy ra trong nội bộ với các truy vấn thực sự có thể khiến dữ liệu biến mất trong các phần của kế hoạch truy vấn: dba.stackexchange.com/questions/1371/ Khăn
RolandoMyQueryDBA

2

BẢNG PHÂN TÍCH cho MyISAM quét toàn bộ bảng và xây dựng lại các số liệu thống kê, được lưu trong (tôi nghĩ) tệp .MYI. Nó hiếm khi cần thiết.

PHÂN TÍCH BẢNG cho InnoDB không làm điều gì đó - nó lặn đề cập. Vấn đề là nó có thể giúp ích, có thể làm cho mọi thứ tồi tệ hơn, hoặc (rất có thể) sẽ không tạo ra bất kỳ sự khác biệt rõ ràng nào (ngoại trừ về số lượng).

Các phiên bản mới hơn hứa hẹn cho phép thay đổi 8 đầu dò không ngẫu nhiên thành (1) ngẫu nhiên hơn, (2) cho phép bạn thay đổi "8" (có những ưu và nhược điểm của việc này!) Và (3) tiết kiệm khi khởi động lại.

Điểm mấu chốt: InnoDB vẫn chưa nhận được 'đúng'. Làm ANALYZE khi bạn cảm thấy thích nó, nhưng đừng nín thở.

Cập nhật

Để diễn đạt lại cụm từ ... ANALYZE TABLEcó tác dụng tạm thời (có thể có lợi, có thể không) đối với việc tối ưu hóa các bảng InnoDB.

"Phiên bản mới hơn": Bắt đầu với 5.6.6 (2012) và MariaDB 10.1 (2014), các số liệu thống kê được xử lý tốt hơn nhiều và ANALYZEhiện tại (1) ít cần thiết hơn và (2) lâu dài hơn.

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.