Tại sao toán tử "IN" quá chậm khi được sử dụng với truy vấn phụ?Toán tử PostgreSQL IN có hiệu suất phụ truy vấn kém
select *
from view1
where id in (1,2,3,4,5,6,7,8,9,10)
order by somedata;
thực hiện trong 9ms.
select *
from view1
where id in (select ext_id
from aggregate_table
order by somedata limit 10)
order by somedata;
thực hiện trong 25000ms và dường như sử dụng quét tuần tự trên view (view1
) thay vì chỉ quét trên khóa chính được trả về bởi subquery như trong thực hiện trong truy vấn đầu tiên.
Các subquery select ext_id from aggregate_table order by somedata limit 10
thực hiện trong 0.1ms
nên sự chậm chạp của truy vấn thứ hai là do quét tuần tự trên view1
đó là một cái nhìn chứa ba công đoàn và khoảng ba tham gia trong mỗi UNION. UNION đầu tiên chứa khoảng 1 triệu hàng, số khác ít hơn nhiều. Tham gia với các bảng có một số hàng 100K. Tuy nhiên, điều đó không liên quan lắm, tôi chỉ muốn hiểu hành vi của toán tử IN.
Điều tôi đang cố gắng thực hiện là lấy kết quả của truy vấn phụ (một bộ khóa chính) và chọn dữ liệu từ chế độ xem phức tạp (view1
) chỉ sử dụng chúng.
Tôi cũng không thể sử dụng
select v1.*
from view1 v1,
aggregate_table at
where v1.id = at.ext_id
order by at.somedata
limit 10
bởi vì tôi không muốn sắp xếp lớn tham gia bằng somedata
. Tôi chỉ muốn chọn 10 kết quả từ khung nhìn bằng các khóa chính và sau đó chỉ sắp xếp các kết quả này.
Câu hỏi đặt ra là tại sao toán tử IN thực hiện nhanh khi tôi liệt kê các khóa này một cách rõ ràng và quá chậm khi tôi sử dụng truy vấn con nhanh trả về cùng một nhóm khóa chính xác?
GIẢI THÍCH PHÂN TÍCH theo yêu cầu
đầu tiên truy vấn - select * from view1 where id in (1,2,3,4,5,6,7,8,9,10) order by somedata;
Sort (cost=348.480..348.550 rows=30 width=943) (actual time=14.385..14.399 rows=10 loops=1)
Sort Key: "india".three
Sort Method: quicksort Memory: 30kB
-> Append (cost=47.650..347.440 rows=30 width=334) (actual time=11.528..14.275 rows=10 loops=1)
-> Subquery Scan "*SELECT* 1" (cost=47.650..172.110 rows=10 width=496) (actual time=11.526..12.301 rows=10 loops=1)
-> Nested Loop (cost=47.650..172.010 rows=10 width=496) (actual time=11.520..12.268 rows=10 loops=1)
-> Hash Join (cost=47.650..87.710 rows=10 width=371) (actual time=11.054..11.461 rows=10 loops=1)
Hash Cond: (hotel.alpha_five = juliet_xray.alpha_five)
-> Bitmap Heap Scan on sierra hotel (cost=42.890..82.800 rows=10 width=345) (actual time=10.835..11.203 rows=10 loops=1)
Recheck Cond: (four = ANY ('quebec'::integer[]))
-> Bitmap Index Scan on seven (cost=0.000..42.890 rows=10 width=0) (actual time=0.194..0.194 rows=10 loops=1)
Index Cond: (four = ANY ('quebec'::integer[]))
-> Hash (cost=4.340..4.340 rows=34 width=30) (actual time=0.184..0.184 rows=34 loops=1)
-> Seq Scan on six juliet_xray (cost=0.000..4.340 rows=34 width=30) (actual time=0.029..0.124 rows=34 loops=1)
-> Index Scan using charlie on juliet_two zulu (cost=0.000..8.390 rows=1 width=129) (actual time=0.065..0.067 rows=1 loops=10)
Index Cond: (zulu.four = hotel.victor_whiskey)
-> Subquery Scan "*SELECT* 2" (cost=4.760..97.420 rows=10 width=366) (actual time=0.168..0.168 rows=0 loops=1)
-> Hash Join (cost=4.760..97.320 rows=10 width=366) (actual time=0.165..0.165 rows=0 loops=1)
Hash Cond: (alpha_xray.alpha_five = juliet_xray2.alpha_five)
-> Nested Loop (cost=0.000..92.390 rows=10 width=340) (actual time=0.162..0.162 rows=0 loops=1)
-> Seq Scan on lima_echo alpha_xray (cost=0.000..8.340 rows=10 width=216) (actual time=0.159..0.159 rows=0 loops=1)
Filter: (four = ANY ('quebec'::integer[]))
-> Index Scan using charlie on juliet_two xray (cost=0.000..8.390 rows=1 width=128) (never executed)
Index Cond: (zulu2.four = alpha_xray.victor_whiskey)
-> Hash (cost=4.340..4.340 rows=34 width=30) (never executed)
-> Seq Scan on six uniform (cost=0.000..4.340 rows=34 width=30) (never executed)
-> Subquery Scan "*SELECT* 3" (cost=43.350..77.910 rows=10 width=141) (actual time=1.775..1.775 rows=0 loops=1)
-> Hash Join (cost=43.350..77.810 rows=10 width=141) (actual time=1.771..1.771 rows=0 loops=1)
Hash Cond: (golf.alpha_five = juliet_xray3.alpha_five)
-> Bitmap Heap Scan on lima_golf golf (cost=38.590..72.910 rows=10 width=115) (actual time=0.110..0.110 rows=0 loops=1)
Recheck Cond: (four = ANY ('quebec'::integer[]))
-> Bitmap Index Scan on victor_hotel (cost=0.000..38.590 rows=10 width=0) (actual time=0.105..0.105 rows=0 loops=1)
Index Cond: (four = ANY ('quebec'::integer[]))
-> Hash (cost=4.340..4.340 rows=34 width=30) (actual time=0.118..0.118 rows=34 loops=1)
-> Seq Scan on six victor_kilo (cost=0.000..4.340 rows=34 width=30) (actual time=0.007..0.063 rows=34 loops=1)
Total runtime: 14.728 ms
thứ hai truy vấn - select * from view1 where id in (select ext_id from aggregate_table order by somedata limit 10) order by somedata;
Sort (cost=254515.780..254654.090 rows=55325 width=943) (actual time=24687.475..24687.488 rows=10 loops=1)
Sort Key: "five".xray_alpha
Sort Method: quicksort Memory: 30kB
-> Hash Semi Join (cost=54300.820..250157.370 rows=55325 width=943) (actual time=11921.783..24687.308 rows=10 loops=1)
Hash Cond: ("five".lima = "delta_echo".lima)
-> Append (cost=54298.270..235569.720 rows=1106504 width=494) (actual time=3412.453..23091.938 rows=1106503 loops=1)
-> Subquery Scan "*SELECT* 1" (cost=54298.270..234227.250 rows=1100622 width=496) (actual time=3412.450..20234.122 rows=1100622 loops=1)
-> Hash Join (cost=54298.270..223221.030 rows=1100622 width=496) (actual time=3412.445..17078.021 rows=1100622 loops=1)
Hash Cond: (three_victor.xray_hotel = delta_yankee.xray_hotel)
-> Hash Join (cost=54293.500..180567.160 rows=1100622 width=470) (actual time=3412.251..12108.676 rows=1100622 loops=1)
Hash Cond: (three_victor.tango_three = quebec_seven.lima)
-> Seq Scan on india three_victor (cost=0.000..104261.220 rows=1100622 width=345) (actual time=0.015..3437.722 rows=1100622 loops=1)
-> Hash (cost=44613.780..44613.780 rows=774378 width=129) (actual time=3412.031..3412.031 rows=774603 loops=1)
-> Seq Scan on oscar quebec_seven (cost=0.000..44613.780 rows=774378 width=129) (actual time=4.142..1964.036 rows=774603 loops=1)
-> Hash (cost=4.340..4.340 rows=34 width=30) (actual time=0.149..0.149 rows=34 loops=1)
-> Seq Scan on alpha_kilo delta_yankee (cost=0.000..4.340 rows=34 width=30) (actual time=0.017..0.095 rows=34 loops=1)
-> Subquery Scan "*SELECT* 2" (cost=4.760..884.690 rows=104 width=366) (actual time=7.846..10.161 rows=104 loops=1)
-> Hash Join (cost=4.760..883.650 rows=104 width=366) (actual time=7.837..9.804 rows=104 loops=1)
Hash Cond: (foxtrot.xray_hotel = delta_yankee2.xray_hotel)
-> Nested Loop (cost=0.000..877.200 rows=104 width=340) (actual time=7.573..9.156 rows=104 loops=1)
-> Seq Scan on four_india foxtrot (cost=0.000..7.040 rows=104 width=216) (actual time=0.081..0.311 rows=104 loops=1)
-> Index Scan using three_delta on oscar alpha_victor (cost=0.000..8.350 rows=1 width=128) (actual time=0.077..0.078 rows=1 loops=104)
Index Cond: (quebec_seven2.lima = foxtrot.tango_three)
-> Hash (cost=4.340..4.340 rows=34 width=30) (actual time=0.216..0.216 rows=34 loops=1)
-> Seq Scan on alpha_kilo quebec_foxtrot (cost=0.000..4.340 rows=34 width=30) (actual time=0.035..0.153 rows=34 loops=1)
-> Subquery Scan "*SELECT* 3" (cost=4.760..457.770 rows=5778 width=141) (actual time=0.264..58.353 rows=5777 loops=1)
-> Hash Join (cost=4.760..399.990 rows=5778 width=141) (actual time=0.253..39.062 rows=5777 loops=1)
Hash Cond: (four_uniform.xray_hotel = delta_yankee3.xray_hotel)
-> Seq Scan on whiskey four_uniform (cost=0.000..315.780 rows=5778 width=115) (actual time=0.112..15.759 rows=5778 loops=1)
-> Hash (cost=4.340..4.340 rows=34 width=30) (actual time=0.117..0.117 rows=34 loops=1)
-> Seq Scan on alpha_kilo golf (cost=0.000..4.340 rows=34 width=30) (actual time=0.005..0.059 rows=34 loops=1)
-> Hash (cost=2.430..2.430 rows=10 width=4) (actual time=0.303..0.303 rows=10 loops=1)
-> Subquery Scan "ANY_subquery" (cost=0.000..2.430 rows=10 width=4) (actual time=0.092..0.284 rows=10 loops=1)
-> Limit (cost=0.000..2.330 rows=10 width=68) (actual time=0.089..0.252 rows=10 loops=1)
-> Index Scan using tango_seven on zulu romeo (cost=0.000..257535.070 rows=1106504 width=68) (actual time=0.087..0.227 rows=10 loops=1)
Total runtime: 24687.975 ms
Bạn có thể cho chúng tôi thấy CHỌN ANALYZE SELECT ...? Có lẽ sử dụng [depesz] (http://explain.depesz.com/) – MatheusOl
Tôi sẽ thử đặt kết quả truy vấn phụ trong bảng tạm thời, và làm IN (chọn id từ cám dỗ). Sự khác biệt là mệnh đề 'giới hạn' có thể khiến trình tối ưu hóa thực thi chọn lựa cho mỗi hàng trong bảng 1. PS này dường như có hiệu quả giống như @Clodoaldo được đề xuất – rootkit
đã cố gắng 'tạo bảng tạm thời aggregate_table_tmp như chọn ext_id từ thứ tự aggregate_table bởi giới hạn somedata 10' và sau đó sử dụng nó trong truy vấn con' select * từ table1 trong đó id in (select ext_id from aggregate_table_tmp) order bởi somedata' - không may mắn. Cùng 25000ms. – Snifff