Tôi đã dành hơn một giờ hôm nay, tôi đã bối rối trước một kế hoạch truy vấn mà tôi không thể hiểu được. Truy vấn là UDPATE
và nó sẽ không chạy TẤT CẢ. Hoàn toàn bế tắc: pg_locks
cho thấy nó cũng không chờ đợi bất cứ điều gì. Bây giờ, tôi không coi mình là người đọc kế hoạch truy vấn tốt nhất hay tệ nhất, nhưng tôi thấy điều này đặc biệt khó khăn. Tôi tự hỏi làm thế nào để đọc những? Có phương pháp luận nào để tuân theo để xác định lỗi không?Làm thế nào tôi có thể "suy nghĩ tốt hơn" khi đọc một kế hoạch truy vấn PostgreSQL? (Ví dụ đính kèm)
Tôi dự định đặt một câu hỏi khác về cách giải quyết vấn đề này, nhưng hiện tại tôi đang nói cụ thể theo số cách đọc các loại kế hoạch này. Vui lòng không trỏ đến bất kỳ hướng dẫn chung nào trừ khi nó giải quyết cụ thể vấn đề này, được đánh dấu bên dưới kế hoạch truy vấn.
QUERY PLAN
--------------------------------------------------------------------------------------------
Nested Loop Anti Join (cost=47680.88..169413.12 rows=1 width=77)
Join Filter: ((co.fkey_style = v.chrome_styleid) AND (co.name = o.name))
-> Nested Loop (cost=5301.58..31738.10 rows=1 width=81)
-> Hash Join (cost=5301.58..29722.32 rows=229 width=40)
Hash Cond: ((io.lot_id = iv.lot_id) AND ((io.vin)::text = (iv.vin)::text))
-> Seq Scan on options io (cost=0.00..20223.32 rows=23004 width=36)
Filter: (name IS NULL)
-> Hash (cost=4547.33..4547.33 rows=36150 width=24)
-> Seq Scan on vehicles iv (cost=0.00..4547.33 rows=36150 width=24)
Filter: (date_sold IS NULL)
-> Index Scan using options_pkey on options co (cost=0.00..8.79 rows=1 width=49)
Index Cond: ((co.fkey_style = iv.chrome_styleid) AND (co.code = io.code))
-> Hash Join (cost=42379.30..137424.09 rows=16729 width=26)
Hash Cond: ((v.lot_id = o.lot_id) AND ((v.vin)::text = (o.vin)::text))
-> Seq Scan on vehicles v (cost=0.00..4547.33 rows=65233 width=24)
-> Hash (cost=20223.32..20223.32 rows=931332 width=44)
-> Seq Scan on options o (cost=0.00..20223.32 rows=931332 width=44)
(17 rows)
Vấn đề với kế hoạch truy vấn này - Tôi tin rằng tôi hiểu được - có lẽ là tốt nhất nói bởi RhodiumToad
(ông chắc chắn là tốt hơn lúc này, vì vậy tôi sẽ đặt cược vào lời giải thích của ông là tốt hơn) của irc://irc.freenode.net/#postgresql
:
oh, kế hoạch đó là khả năng disasterous vấn đề với kế hoạch đó là nó đang chạy một hashjoin cực kỳ đắt đối với mỗi hàng vấn đề là các hàng = 1 ước tính từ khác tham gia và các nhà quy hoạch cho rằng đó là ok để đặt một ly truy vấn đắt tiền trong đường dẫn bên trong của một tổ hợp nơi đường dẫn bên ngoài được ước tính chỉ trả về một hàng. vì, rõ ràng, theo ước tính của người lập kế hoạch phần đắt tiền sẽ chỉ được chạy một lần nhưng điều này có xu hướng rõ ràng thực sự gây rối trong thực tế vấn đề là người lập kế hoạch tin rằng ước tính riêng của mình lý tưởng, người lập kế hoạch cần phải biết sự khác biệt giữa "ước trở 1 hàng" và "không thể trả về nhiều hơn 1 hàng" nhưng nó không phải là ở tất cả rõ ràng làm thế nào để kết hợp đó vào mã hiện
Ông tiếp tục nói:
nó có thể ảnh hưởng đến bất kỳ tham gia nào, nhưng thường tham gia chống lại subqueries là khả năng
nhất Bây giờ khi tôi đọc kế hoạch này, điều đầu tiên tôi nhận thấy là Nested Loop Anti Join
, điều này đã có một chi phí 169,413
(Tôi sẽ dính vào cận trên). Anti-Join này phân tích thành kết quả của một số Nested Loop
với chi phí 31,738
và kết quả là Hash Join
với chi phí là 137,424
. Bây giờ, số 137,424
, là nhiều lớn hơn 31,738
vì vậy tôi biết sự cố là Tham gia băm. Sau đó, tôi tiếp tục đến EXPLAIN ANALYZE
phân đoạn Hash Tham gia bên ngoài truy vấn. Nó được thực hiện trong 7 giây. Tôi đã đảm bảo có các chỉ mục trên (lot_id, vin) và (co.code và v.code) - đã có. Tôi đã vô hiệu hóa seq_scan
và hashjoin
riêng lẻ và nhận thấy tốc độ tăng ít hơn 2 giây. Không đủ gần để giải thích tại sao nó không tiến triển sau một giờ.
Nhưng, sau tất cả điều này tôi hoàn toàn sai! Có, đó là phần chậm hơn của truy vấn, nhưng vì bit rows="1"
(tôi cho rằng nó nằm trên Nested Loop Anti Join
). Có hướng dẫn nào giúp tôi xác định các loại vấn đề này không. Ở đây nó là một lỗi (thiếu khả năng) trong kế hoạch sai ước tính số lượng hàng?Làm thế nào tôi phải đọc vào điều này để đi đến cùng một kết luận RhodiumToad
đã làm?
Chỉ đơn giản là rows="1"
đó là nghĩa vụ phải kích hoạt tôi tìm ra điều này?
Tôi đã chạy VACUUM FULL ANALYZE
trên tất cả các bảng có liên quan và đây là Postgresql 8.4.
Đây là một câu trả lời tuyệt vời, nhưng bạn đang nói về điều gì khi bạn nói 'tham gia vào co'? Tôi tin rằng 'RhodiumToads' giải thích vấn đề bởi vì nó có vẻ chính xác? Bạn đang giải thích điều tương tự hay điều gì đó khác? –
Điều tương tự. Tham gia vào 'co' là' Chỉ mục Quét bằng cách sử dụng tùy chọn_pkey trên các tùy chọn co' nút bên trong của vòng lặp lồng nhau tham gia. Nó có hai điều kiện mà người lập kế hoạch có thể nghĩ không hợp lý sẽ dẫn đến một hàng đầu ra.Nếu bạn cố gắng chạy truy vấn đó và xem có bao nhiêu hàng nó thực sự trả về, bạn có thể xác minh xem đây có phải là trường hợp không. Ước tính xấu cho các vị từ tương quan là một vấn đề đã biết. Có một số cuộc thảo luận về điều này trên danh sách hiệu suất: http://archives.postgresql.org/pgsql-performance/2009-06/msg00055.php –