Tôi có một truy vấn tương đối đơn giản trên một bảng có 1,5M hàng:
SELECT mtid FROM publication
WHERE mtid IN (9762715) OR last_modifier=21321
LIMIT 5000;
EXPLAIN ANALYZE
đầu ra:
Limit (cost=8.84..12.86 rows=1 width=8) (actual time=0.985..0.986 rows=1 loops=1) -> Bitmap Heap Scan on publication (cost=8.84..12.86 rows=1 width=8) (actual time=0.984..0.985 rows=1 loops=1) Recheck Cond: ((mtid = 9762715) OR (last_modifier = 21321)) -> BitmapOr (cost=8.84..8.84 rows=1 width=0) (actual time=0.971..0.971 rows=0 loops=1) -> Bitmap Index Scan on publication_pkey (cost=0.00..4.42 rows=1 width=0) (actual time=0.295..0.295 rows=1 loops=1) Index Cond: (mtid = 9762715) -> Bitmap Index Scan on publication_last_modifier_btree (cost=0.00..4.42 rows=1 width=0) (actual time=0.674..0.674 rows=0 loops=1) Index Cond: (last_modifier = 21321) Total runtime: 1.027 ms
Cho đến nay rất tốt, nhanh chóng và sử dụng các chỉ mục có sẵn.
Bây giờ, nếu tôi sửa đổi một truy vấn chỉ một chút, kết quả sẽ là:
SELECT mtid FROM publication
WHERE mtid IN (SELECT 9762715) OR last_modifier=21321
LIMIT 5000;
Đầu EXPLAIN ANALYZE
ra là:
Limit (cost=0.01..2347.74 rows=5000 width=8) (actual time=2735.891..2841.398 rows=1 loops=1) -> Seq Scan on publication (cost=0.01..349652.84 rows=744661 width=8) (actual time=2735.888..2841.393 rows=1 loops=1) Filter: ((hashed SubPlan 1) OR (last_modifier = 21321)) SubPlan 1 -> Result (cost=0.00..0.01 rows=1 width=0) (actual time=0.001..0.001 rows=1 loops=1) Total runtime: 2841.442 ms
Không quá nhanh và sử dụng quét seq ...
Tất nhiên, truy vấn ban đầu được chạy bởi ứng dụng phức tạp hơn một chút và thậm chí chậm hơn, và tất nhiên bản gốc được tạo ra bởi chế độ ngủ đông thì không (SELECT 9762715)
, nhưng sự chậm chạp thậm chí còn có cho điều đó (SELECT 9762715)
! Truy vấn được tạo bởi hibernate, do đó, việc thay đổi chúng là một thách thức và một số tính năng không khả dụng (ví dụ: UNION
không khả dụng, sẽ nhanh).
Những câu hỏi
- Tại sao chỉ mục không thể được sử dụng trong trường hợp thứ hai? Làm thế nào chúng có thể được sử dụng?
- Tôi có thể cải thiện hiệu suất truy vấn theo một cách khác không?
Suy nghĩ thêm
Có vẻ như chúng ta có thể sử dụng trường hợp đầu tiên bằng cách thực hiện thủ công CHỌN và sau đó đưa danh sách kết quả vào truy vấn. Ngay cả với 5000 số trong danh sách IN (), nó nhanh hơn bốn lần so với giải pháp thứ hai. Tuy nhiên, nó chỉ có vẻ SAU (cũng vậy, nó có thể nhanh hơn 100 lần :)). Hoàn toàn không thể hiểu được tại sao trình hoạch định truy vấn sử dụng một phương pháp hoàn toàn khác cho hai truy vấn này, vì vậy tôi muốn tìm một giải pháp đẹp hơn cho vấn đề này.
(SELECT 9762715)
.
(SELECT 9762715)
. Đối với câu hỏi ngủ đông: nó có thể được thực hiện, nhưng yêu cầu viết lại mã nghiêm túc, vì chúng tôi có các tiêu chí ngủ đông do người dùng định nghĩa được dịch nhanh chóng. Vì vậy, về cơ bản, chúng tôi sẽ sửa đổi chế độ ngủ đông là một công việc khổng lồ với rất nhiều tác dụng phụ có thể xảy ra.
JOIN
thay vìIN ()
? Ngoài ra, đãpublication
được phân tích gần đây?