Trong MySQL, thứ tự của các cột trong mệnh đề WHERE có ảnh hưởng đến hiệu năng truy vấn không?


38

Tôi đang gặp vấn đề về hiệu năng trên các truy vấn cơ sở dữ liệu nhất định có tập kết quả lớn có thể.

Truy vấn trong câu hỏi, tôi có ba ANDs trong mệnh đề WHERE

Liệu thứ tự của các mệnh đề có vấn đề?

Như trong, nếu tôi đặt mệnh đề ASI_EVENT_TIME trước tiên (vì điều đó sẽ loại bỏ hầu hết các kết quả ra khỏi bất kỳ mệnh đề nào.

Điều đó sẽ cải thiện thời gian chạy trên truy vấn?

TRUY VẤN:

SELECT DISTINCT  activity_seismo_info.* 
FROM `activity_seismo_info` 
WHERE 
    activity_seismo_info.ASI_ACTIVITY_ID IS NOT NULL  AND 
    activity_seismo_info.ASI_SEISMO_ID IN (43,44,...,259) AND 
    (
        activity_seismo_info.ASI_EVENT_TIME>='2011-03-10 00:00:00' AND 
        activity_seismo_info.ASI_EVENT_TIME<='2011-03-17 23:59:59'
    ) 

ORDER BY activity_seismo_info.ASI_EVENT_TIME DESC

GIẢI THÍCH truy vấn:

+----+-------------+---------+-------+---------------------------+--------------+---------+------+-------+-----------------------------+ 
| id | select_type | table   | type  | possible_keys             | key          | key_len | ref  | rows  | Extra                       |
+----+-------------+---------+-------+---------------------------+--------------+---------+------+-------+-----------------------------+ 
|  1 | SIMPLE      | act...o | range | act...o_FI_1,act...o_FI_2 | act...o_FI_1 | 5       | NULL | 65412 | Using where; Using filesort |
+----+-------------+---------+-------+---------------------------+--------------+---------+------+-------+-----------------------------+

Sử dụng:

PHP 5.2

MySQL 5.0.51a-3ubfox5.4

Tuyên truyền 1.3

Bản giao hưởng 1.2.5


ĐẶT HÀNG B có lẽ là những gì mất quá nhiều thời gian. "Sử dụng filesort" có thể cực kỳ chậm. Tôi đã thấy việc đặt hàng trong logic ứng dụng nhanh hơn rất nhiều so với việc sử dụng ORDER BY.
maclema

Tôi đã hỏi câu hỏi tương tự một lúc trước (trước trang web này) trên stackoverflow. Kiểm tra các liên kết cho câu trả lời tôi nhận được ở đó. stackoverflow.com/questions/3805863/ Mạnh
Scott

2
@maclema - Trừ khi ứng dụng của bạn chạy trên một máy nhanh hơn nhiều so với cơ sở dữ liệu của bạn, khẳng định của bạn chắc chắn là không đúng, chưa kể đến gánh nặng vô nghĩa của tất cả logic sắp xếp đó trong ứng dụng của bạn. order bythuộc về cơ sở dữ liệu.
Jack Douglas

Câu trả lời:


24

Tôi không nghĩ vậy. Trình tối ưu hóa truy vấn phải đủ thông minh.

Bạn có thể thử sắp xếp lại các mệnh đề WHERE và thấy rằng GIẢI THÍCH cho bạn biết điều tương tự trong từng trường hợp.


Về những gì có thể được thực hiện để tối ưu hóa truy vấn này: Có chỉ mục nào trên ASI_EVENT_TIME không? (đây là điều quan trọng nhất tôi nghĩ cho truy vấn này khi bạn cũng sắp xếp kết quả bằng cách sử dụng nó).

Có các chỉ mục trên hai trường khác (ASI_SEISMO_ID và ASI_ACTIVITY_ID) không?

Nó sẽ hữu ích nếu bạn đăng cấu trúc bảng.


Tôi chưa bao giờ nghĩ sẽ tạo ra một chỉ mục về thời gian sự kiện. Tôi sẽ thử vào ngày mai trên dev db và xem có sự khác biệt đáng chú ý nào không.
Patrick

@Patrick Giả sử tất cả các truy vấn khác sẽ sử dụng chỉ mục này đang sắp xếp ngày này theo thứ tự giảm dần, bạn cũng muốn đặt khóa chỉ mục (Activity_seismo_info.ASI_EVENT_TIME) theo thứ tự giảm dần.
Matt M

@MattM Tôi không biết rằng bạn CÓ THỂ đặt một khóa chỉ mục. Tuyệt vời Nếu tôi đặt thứ tự khóa chỉ mục, điều đó có nhất thiết ảnh hưởng đến thứ tự hiệu suất theo hướng ngược lại đến mức tệ hơn không có khóa chỉ mục không?
Patrick

@Patrick Bạn nói đúng. Bộ não của tôi bị mắc kẹt trong đất SQL Server. Bạn có thể chỉ định thứ tự sắp xếp trong MYSQL và nó sẽ phân tích cú pháp, nhưng nó bị bỏ qua. Tất cả các chỉ mục được sắp xếp theo thứ tự tăng dần trong MYSQL. Xin lỗi vì sự nhầm lẫn.
Matt M

13

Từ tài liệu :

Nếu bảng có chỉ mục nhiều cột, bất kỳ tiền tố ngoài cùng bên trái của chỉ mục có thể được sử dụng bởi trình tối ưu hóa để tìm hàng. Ví dụ: nếu bạn có chỉ mục ba cột trên (col1, col2, col3), bạn đã lập chỉ mục các khả năng tìm kiếm trên (col1), (col1, col2) và (col1, col2, col3).

MySQL không thể sử dụng một chỉ mục nếu các cột không tạo thành tiền tố ngoài cùng bên trái của chỉ mục.

Vì vậy, có, nó phải giống như thứ tự của các cột trong một chỉ mục ghép .


4
Nếu bảng có chỉ mục nhiều cột chọn các cột từ các vấn đề bên trái - nhưng thứ tự bạn chọn không quan trọng. Vì vậy, nếu bạn có chỉ số a, b, c và bạn làm WHERE c = 'foo' AND a = 'bar' AND b = 'foobar'và chỉ mục vẫn đủ điều kiện để sử dụng.
texelate

10

Không, nó không thành vấn đề.

Trình tối ưu hóa thực hiện một loạt các biến đổi đơn giản ngay sau khi phân tích cú pháp SQL - đây là một trong số chúng.


8

Ở đâu đó foo VÀ thanh

tối ưu hóa giống như

Thanh ở đâu và foo

Tuy nhiên,

Ở đâu không bằng # 1 và không bằng # 2

Không thể tối ưu hóa cả hai phần. Ví dụ,

Ở ĐÂU GIỮA 1 và 3 VÀ b> 17

không thể sử dụng tốt INDEX (a, b) hoặc INDEX (b, a)

Để diễn đạt nó một cách khác nhau, mọi phép thử '=' AND'd với nhau trong mệnh đề WHERE được sử dụng trước tiên, sau đó một phép không - '=' (IN, GIỮA,>, v.v.) có thể được xử lý. Không có nhiều hơn một có thể được tối ưu hóa hiệu quả.

Truy vấn của bạn có 3 mệnh đề như vậy.

Hóa ra, INDEX (EVENT_TIME) có lẽ là hữu ích nhất - nó sẽ giúp với một trong các AND và nó có thể được sử dụng để tránh "fileort" cho ORDER BY.

Nếu không có hàng trùng lặp (tại sao cái quái đó lại có?), Thì hãy loại bỏ DISTINCT. Điều đó gây ra nhiều nỗ lực hơn nữa.

Vui lòng cung cấp SHOW CREATE TABLE và SHOW TABLE STATUS khi đặt câu hỏi về hiệu suất.

Cập nhật ... Các phiên bản mới hơn (ví dụ: MySQL 5.7), trong một số trường hợp, có thể xử lý IN( list of constants )gần như như thế =. Để chơi an toàn, hãy tuân theo thứ tự này (mỗi phần là tùy chọn):

  1. Bất kỳ số lượng =.
  2. Một số INs.
  3. Nhiều nhất là một phạm vi.

1

MySQL nơi tài liệu tối ưu hóa nói:

Bạn có thể muốn viết lại các truy vấn của mình để làm cho các phép toán số học nhanh hơn, trong khi hy sinh khả năng đọc. Vì MySQL thực hiện tối ưu hóa tương tự tự động , bạn thường có thể tránh công việc này và để truy vấn ở dạng dễ hiểu và dễ bảo trì hơn. Một số tối ưu hóa được thực hiện bởi MySQL như sau:

  • ...

  • Đối với mỗi bảng trong một liên kết, WHERE đơn giản hơn được xây dựng để có được đánh giá WHERE nhanh cho bảng và cũng để bỏ qua các hàng càng sớm càng tốt .

  • Mỗi chỉ mục bảng được truy vấn và chỉ mục tốt nhất được sử dụng trừ khi trình tối ưu hóa tin rằng sử dụng quét bảng hiệu quả hơn . Tại một thời điểm, quá trình quét được sử dụng dựa trên việc chỉ mục tốt nhất có kéo dài hơn 30% bảng hay không, nhưng tỷ lệ cố định không còn xác định lựa chọn giữa sử dụng chỉ mục hay quét. Trình tối ưu hóa bây giờ phức tạp hơn và dựa trên ước tính của nó dựa trên các yếu tố bổ sung như kích thước bảng, số lượng hàng và kích thước khối I / O.

Cách này là hợp lý để trình tối ưu hóa truy vấn bỏ qua thứ tự CÁCH, chúng tôi đã sử dụng các cột trong truy vấn (Không chỉ MySQL mà SQL là ngôn ngữ khai báo và phải làm những gì chúng tôi muốn không theo cách chúng tôi muốn).

Tuy nhiên, tôi vẫn thích có cùng loại cho các cột của khóa tổng hợp trong truy vấn nhưng đôi khi không thể tránh khỏi khi chúng tôi sử dụng ORM hoặc ActiveRecord, trong một số khung như yii2, việc tùy chỉnh các tiêu chí quan hệ sẽ được thêm vào cuối một điều kiện "bật" nhưng chúng ta vẫn cần các khả năng của QueryBuilders trong các phần khác nhau của ứng dụng.


-2

MỌI trường được sử dụng trong mệnh đề WHERE / HAVING của bạn và có tính chọn lọc cao (số lượng giá trị duy nhất / tổng số bản ghi> 10% ~ 20%) PHẢI được lập chỉ mục.

Vì vậy, nếu ASI_EVENT_TIMEcột của bạn có nhiều giá trị có thể, trước tiên hãy lập chỉ mục tất cả. Sau đó, như @ypercube đã nói, hãy thử sắp xếp lại chúng và xem những gì GIẢI THÍCH nói với bạn. Nên là tất cả xung quanh như nhau.

Ngoài ra, muốn bạn có một cái nhìn về Bộ lọc SQL THÍCH Lập chỉ mục . Mặc dù đó không phải là những gì bạn cần một câu trả lời, nhưng bạn vẫn sẽ tìm hiểu về cách lập chỉ mục hoạt động dưới mui xe.

* Chỉnh sửa: Tham khảo các liên kết được cung cấp dưới đây trong các nhận xét để tìm hiểu thêm về lập chỉ mục.


8
-1 Lập chỉ mục mỗi cột KHÔNG phải là cách thực hành tốt nhất. Mỗi chỉ số chi phí bạn theo nhiều cách. Hãy chắc chắn rằng bạn chọn các chỉ mục tốt, thường sẽ bao gồm nhiều cột, thường theo thứ tự chọn lọc và tần suất được sử dụng. Đây có thể là SQL Server nghiêng, nhưng thông tin chỉ mục vẫn hợp lệ: sqlskills.com/BLOGS/KIMBERLY/post/ ,.
Eric Humphrey - lotahelp

@Eric Humphrey +1 Để biết giải thích và liên kết đến trang web của Kimberly.
Matt M

bạn đã sai, việc lập chỉ mục trên cột đôi khi làm ảnh hưởng đến hiệu suất của bạn đối với các truy vấn được chọn: mysqlperformanceblog.com/2007/08/28/ . Bạn KHÔNG BAO GIỜ nên sử dụng quy tắc ngón tay cái: đôi khi nó hoạt động, đôi khi không.
sumar

Phải, tôi đồng ý. Tuy nhiên, điều này là hợp lệ trong trường hợp độ chọn lọc giá trị thấp. Xem xét loại dữ liệu mà Patrick (tác giả câu hỏi này) sử dụng, đó là DATETIME, nên lập chỉ mục. Thông thường loại trường này có tập giá trị khá lớn, trừ khi có một tình huống kỳ lạ khi anh ta chỉ sử dụng một vài ngày có thể. * Tôi sẽ chỉnh sửa câu trả lời của tôi ở trên để đưa ra tuyên bố rõ ràng và hợp lệ hơn.
Mắt
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.