Tại sao CHỌN * có cường độ nhanh hơn CHỌN foo?


28

Hãy xem xét một bảng các giá trị và giá trị băm, như vậy:

+------------+----------+------+-----+---------+----------------+
| Field      | Type     | Null | Key | Default | Extra          |
+------------+----------+------+-----+---------+----------------+
| id         | int(11)  | NO   | PRI | NULL    | auto_increment |
| val        | char(9)  | NO   |     | NULL    |                |
| val_hashed | char(50) | YES  |     | NULL    |                |
+------------+----------+------+-----+---------+----------------+

Truy vấn sau kết thúc sau 0,00 giây:

SELECT * FROM hashes ORDER BY 1 DESC LIMIT 1;

Tuy nhiên, truy vấn này mất 3 phút 17 giây:

SELECT val FROM hashes ORDER BY 1 DESC LIMIT 1;

Tôi thấy rằng trong khi truy vấn đang chạy, danh sách quy trình hiển thị nó dưới dạng trạng thái Sorting result. Tình hình là hoàn toàn tái sản xuất. Lưu ý rằng có một quá trình khác thực hiện các INSERThoạt động trên bàn liên tục.

Tại sao truy vấn cụ thể sẽ mất nhiều thời gian hơn so với *truy vấn? Tôi luôn tin rằng *các truy vấn nên được tránh cụ thể vì lý do hiệu suất.


7
Các câu lệnh đầu tiên có lẽ sử dụng chỉ mục khóa chính trên idđể tìm hàng đầu tiên. Cái thứ hai cần sắp xếp kết quả hoàn chỉnh trên cột (không được lập chỉ mục) val.
a_horse_with_no_name

8
Các ORDER BY NUMBERcú pháp là khá dễ bị lỗi.
usr

2
Thêm vào nhận xét cuối cùng của bạn, SELECT *kết hợp với chỉ mục cột trong ORDER BYđang làm xáo trộn cột nào đang được sắp xếp - một lý do khác để tránh *s ...
lc.

@lc., Ý bạn là gì?
Pacerier

@Pacerier Ý tôi *là không rõ ràng. Vì vậy, nói "đưa cho tôi tất cả các cột và sắp xếp theo cột thứ ba" có ý nghĩa quyết định như nói "hãy đi siêu thị và cho tôi biết bạn đã vượt qua bao nhiêu đèn giao thông"
lc.

Câu trả lời:


33

Các cụm từ ORDER BY 1đề cập đến các cột khác nhau; trong lần đầu tiên nó sẽ được id, trong lần thứ hai val. Vì idlà chìa khóa nên nó sẽ được lập chỉ mục và order bysẽ là một khối lượng công việc không đáng kể. Để order by valTuy nhiên, hệ thống này sẽ phải lấy mỗi hàng, sắp xếp hoàn chỉnh bảng bằng cách val, sau đó chọn chỉ là một trong những hàng.

Thay đổi cả hai truy vấn thành order by idvà tôi nghĩ thời gian thực hiện của bạn sẽ gần như giống hệt nhau.


3
Đôi khi những câu hỏi khó nhất là những câu hỏi đang nhìn chằm chằm vào chúng ta. Cảm ơn, Michael!
dotancohen

7

Sự khác biệt hiệu suất trong truy vấn của bạn được giải thích tốt bởi MG. Tôi sẽ giải quyết điều này:

Tôi luôn tin rằng * nên tránh các truy vấn cụ thể vì lý do hiệu suất.

select *Không có hình phạt cụ thể của chính nó, nó là vấn đề khi sử dụng sai. Trong một truy vấn bảng đơn, nó hoạt động tốt. bây giờ nối bảng này với bảng khác với 20 cột và sau đó thêm phép nối vào 5 bảng khác với nhiều cột. BÂY GIỜ nó là một vấn đề. Vì vậy, những người dạy rộng rãi, hỗ trợ ban nhạc "không bao giờ làm X" mà không giải thích lý do tại sao.


3
SELECT *có thể là một vấn đề ngay cả đối với truy vấn một bảng. Ví dụ, SELECT * FROM hashes ORDER BY val;có thể sẽ thực hiện quét toàn bộ bảng và sau đó sắp xếp SELECT val FROM hashes ORDER BY val;chỉ thực hiện quét toàn bộ chỉ mục và không sắp xếp (giả sử chỉ mục tồn tại trên val). Vì vậy, sẽ không bao giờ đau lòng khi chỉ chọn kết quả mà chúng ta cần.
ypercubeᵀᴹ

Tôi giả sử bạn đã thấy điều này? sqlblog.com/bloss/aaron_bertrand/archive/2009/10/10/ từ
Max Vernon

@ypercube, Điều đó có xảy ra ngay cả khi chúng tôi select(*)chỉ được sử dụng làm mục phụ không? Vì là một lựa chọn được nhúng, nên MySQL không đủ thông minh để tìm ra các cột thực sự cần chọn?
Pacerier

Trình tối ưu hóa mysP @Pacerier có các mức độ "thông minh" khác nhau, tùy thuộc vào phiên bản bạn đang sử dụng. Trong gerneal, nó khá là ngớ ngẩn đối với các truy vấn con lồng nhau, vì vậy bất cứ điều gì bạn có thể giúp anh ta, nó đều tốt.
ypercubeᵀᴹ

@ypercube, À, nếu chỉ thông minh như pssql.
Pacerier
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.