Khi làm việc với cơ sở dữ liệu lớn, hoạt động tốt hơn, IN
hoặcOR
trong phần SQL Where
?
Có sự khác biệt nào về cách chúng được thực thi không?
Khi làm việc với cơ sở dữ liệu lớn, hoạt động tốt hơn, IN
hoặcOR
trong phần SQL Where
?
Có sự khác biệt nào về cách chúng được thực thi không?
Câu trả lời:
Tôi giả sử bạn muốn biết sự khác biệt hiệu suất giữa các điều sau đây:
WHERE foo IN ('a', 'b', 'c')
WHERE foo = 'a' OR foo = 'b' OR foo = 'c'
Theo hướng dẫn cho MySQL nếu các giá trị không đổi IN
sắp xếp danh sách và sau đó sử dụng tìm kiếm nhị phân. Tôi sẽ tưởng tượng rằng OR
đánh giá chúng từng cái một không theo thứ tự cụ thể. Vì vậy, IN
là nhanh hơn trong một số trường hợp.
Cách tốt nhất để biết là lập hồ sơ cả trên cơ sở dữ liệu của bạn với dữ liệu cụ thể của bạn để xem cái nào nhanh hơn.
Tôi đã thử cả hai trên một MySQL với 1000000 hàng. Khi cột được lập chỉ mục, không có sự khác biệt rõ rệt về hiệu suất - cả hai đều gần như ngay lập tức. Khi cột không được lập chỉ mục, tôi nhận được các kết quả sau:
SELECT COUNT(*) FROM t_inner WHERE val IN (1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000);
1 row fetched in 0.0032 (1.2679 seconds)
SELECT COUNT(*) FROM t_inner WHERE val = 1000 OR val = 2000 OR val = 3000 OR val = 4000 OR val = 5000 OR val = 6000 OR val = 7000 OR val = 8000 OR val = 9000;
1 row fetched in 0.0026 (1.7385 seconds)
Vì vậy, trong trường hợp này phương thức sử dụng OR chậm hơn khoảng 30%. Thêm nhiều điều khoản làm cho sự khác biệt lớn hơn. Kết quả có thể khác nhau trên các cơ sở dữ liệu khác và trên dữ liệu khác.
IN
phương thức giúp tối ưu hóa dễ dàng hơn so với toàn bộ các OR
mệnh đề có thể liên quan . Tôi sẽ ngạc nhiên nếu có một động cơ mà OR
phương pháp nhanh hơn, nhưng tôi không ngạc nhiên rằng có những lúc OR chậm hơn.
OR
s bằng một IN
?
Cách tốt nhất để tìm hiểu là nhìn vào Kế hoạch thực hiện.
Tôi đã thử nó với Oracle và nó hoàn toàn giống nhau.
CREATE TABLE performance_test AS ( SELECT * FROM dba_objects );
SELECT * FROM performance_test
WHERE object_name IN ('DBMS_STANDARD', 'DBMS_REGISTRY', 'DBMS_LOB' );
Mặc dù truy vấn sử dụng IN
, Kế hoạch thực hiện nói rằng nó sử dụngOR
:
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 8 | 1416 | 163 (2)| 00:00:02 |
|* 1 | TABLE ACCESS FULL| PERFORMANCE_TEST | 8 | 1416 | 163 (2)| 00:00:02 |
--------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("OBJECT_NAME"='DBMS_LOB' OR "OBJECT_NAME"='DBMS_REGISTRY' OR
"OBJECT_NAME"='DBMS_STANDARD')
INLIST ITERATOR
hoạt động, nó sẽ chọn nếu có một chỉ mục mà nó có thể sử dụng. Tuy nhiên, khi tôi đã thử nó, cả hai IN
và OR
kết thúc với cùng một kế hoạch thực hiện.
Toán tử OR cần một quy trình đánh giá phức tạp hơn nhiều so với cấu trúc IN vì nó cho phép nhiều điều kiện, không chỉ bằng IN.
Đây là một cái giống như những gì bạn có thể sử dụng với OR nhưng không tương thích với IN: lớn hơn. lớn hơn hoặc bằng nhau, ít hơn, ít hơn hoặc bằng nhau, THÍCH và một số khác giống như lời tiên tri REGEXP_LIKE. Ngoài ra, xem xét rằng các điều kiện có thể không luôn luôn so sánh cùng một giá trị.
Đối với trình tối ưu hóa truy vấn, việc quản lý toán tử IN dễ dàng hơn vì chỉ là cấu trúc xác định toán tử OR trên nhiều điều kiện với toán tử = trên cùng một giá trị. Nếu bạn sử dụng toán tử OR, trình tối ưu hóa có thể không cho rằng bạn luôn sử dụng toán tử = trên cùng một giá trị và, nếu nó không thực hiện công phu sâu hơn và phức tạp hơn nhiều, có lẽ có thể loại trừ rằng có thể chỉ có = toán tử cho cùng một giá trị trên tất cả các điều kiện liên quan, với kết quả là các phương pháp tìm kiếm được tối ưu hóa như tìm kiếm nhị phân đã được đề cập.
[EDIT] Có lẽ trình tối ưu hóa có thể không thực hiện quy trình đánh giá IN được tối ưu hóa, nhưng điều này không loại trừ rằng một lần nó có thể xảy ra (với nâng cấp phiên bản cơ sở dữ liệu). Vì vậy, nếu bạn sử dụng toán tử OR mà công phu tối ưu hóa sẽ không được sử dụng trong trường hợp của bạn.
OR
có ý nghĩa (từ quan điểm dễ đọc), khi có ít giá trị được so sánh.
IN
là đặc biệt hữu ích. khi bạn có một nguồn động, mà bạn muốn các giá trị được so sánh.
Một cách khác là sử dụng một JOIN
bảng tạm thời.
Tôi không nghĩ hiệu suất nên là một vấn đề, miễn là bạn có các chỉ số cần thiết.
Tôi đã thực hiện một truy vấn SQL với số lượng lớn OR (350). Postgres làm điều đó 437,80ms .
Bây giờ sử dụng IN:
23,18ms