2010-08-19 27 views
5

Tôi có một truy vấn chạy trong khoảng 5 giây trên Postgres 8.4. Nó chọn dữ liệu từ một khung nhìn được nối với một số bảng khác, nhưng cũng sử dụng chức năng cửa sổ lag(), tức là.Truy vấn đóng gói Postgres trong chế độ xem làm cho nó cực kỳ chậm

SELECT *, lag(column1) OVER (PARTITION BY key1 ORDER BY ...), lag(...) 
FROM view1 v 
JOIN othertables USING (...) 
WHERE ... 

Để thuận tiện Tôi tạo ra một cái nhìn mới mà chỉ đơn giản có

SELECT *, lag(column1) OVER (PARTITION BY key1 ORDER BY ...), lag(...) 
FROM view1 v 

và sau đó chọn từ đó, sử dụng tất cả các khác tham gia và các bộ lọc như trước đây. Trước sự ngạc nhiên của tôi, truy vấn này không hoàn thành trong 12 phút (tôi đã dừng nó tại thời điểm đó). Rõ ràng Postgres đã chọn một kế hoạch thực hiện khác. Làm thế nào để làm cho nó không làm điều đó, tức là. sử dụng cùng một kế hoạch như trong truy vấn ban đầu? Tôi đã nghĩ rằng một cái nhìn không nên thay đổi kế hoạch thực hiện, nhưng hình như nó có.

Chỉnh sửa: còn gì nữa, tôi nhận thấy rằng ngay cả khi tôi sao chép nội dung của chế độ xem đầu tiên sang chế độ xem thứ hai, vẫn còn không trả lại.

Chỉnh sửa 2: OK, tôi đã đơn giản hóa truy vấn đủ để đăng các gói.

Sử dụng quan điểm (điều này không trả lại trong bất kỳ thời gian hợp lý):

Subquery Scan sp (cost=5415201.23..5892463.97 rows=88382 width=370) 
    Filter: (((sp.ticker)::text ~~ 'Some Ticker'::text) AND (sp.price_date >= '2010-06-01'::date)) 
    -> WindowAgg (cost=5415201.23..5680347.20 rows=53029193 width=129) 
     -> Sort (cost=5415201.23..5441715.83 rows=53029193 width=129) 
       Sort Key: sp.stock_id, sp.price_date 
       -> Hash Join (cost=847.87..1465139.61 rows=53029193 width=129) 
        Hash Cond: (sp.stock_id = s.stock_id) 
        -> Seq Scan on stock_prices sp (cost=0.00..1079829.20 rows=53029401 width=115) 
        -> Hash (cost=744.56..744.56 rows=29519 width=18) 
          -> Seq Scan on stocks s (cost=0.00..744.56 rows=29519 width=18) 

Lấy chức năng cửa sổ ra khỏi quan điểm và đưa vào truy vấn chính nó (điều này trả về ngay lập tức):

WindowAgg (cost=34.91..34.95 rows=7 width=129) 
    -> Sort (cost=34.91..34.92 rows=7 width=129) 
     Sort Key: sp.stock_id, sp.price_date 
     -> Nested Loop (cost=0.00..34.89 rows=7 width=129) 
       -> Index Scan using stocks_ticker_unique on stocks s (cost=0.00..4.06 rows=1 width=18) 
        Index Cond: ((ticker)::text = 'Some Ticker'::text) 
        Filter: ((ticker)::text ~~ 'Some Ticker'::text) 
       -> Index Scan using stock_prices_id_date_idx on stock_prices sp (cost=0.00..30.79 rows=14 width=115) 
        Index Cond: ((sp.stock_id = s.stock_id) AND (sp.price_date >= '2010-06-01'::date)) 

Vì vậy, có vẻ như trong trường hợp chậm, nó cố gắng áp dụng chức năng cửa sổ cho tất cả dữ liệu trước và sau đó lọc, có thể là vấn đề. Tôi không biết tại sao nó làm điều đó, mặc dù.

+0

+1, nhưng tôi thực sự nghi ngờ bạn sẽ cần phải điền vào các phần '...' trước khi ai đó có thể chẩn đoán những gì đang xảy ra. – Edmund

+0

Tôi có thể, nhưng truy vấn nếu khá phức tạp và tôi sẽ phải giải thích tất cả các bảng có liên quan trông như thế nào. Câu hỏi của tôi là nhiều hơn về một giải pháp chung cho điều này thay vì truy vấn cụ thể này: có cách nào để nói cho Postgres "xem qua" một khung nhìn và sử dụng cùng một kế hoạch truy vấn như thể tôi đã nhập trực tiếp câu lệnh SQL. – EMP

+1

Đăng kế hoạch thực hiện truy vấn? GIẢI THÍCH CHỌN ... –

Trả lời

2

Sự khác biệt giữa hai gói đến từ việc tham gia tổng hợp. Điều này ngăn cản việc sử dụng một kế hoạch lặp lồng nhau. Khi bạn sử dụng tổng hợp trong chế độ xem của mình, bạn đặt mình vào trường hợp không thuận lợi đó.

này, ví dụ, sẽ hầu như luôn luôn dẫn đến một kế hoạch hợp nhất hoặc băm tham gia vào hai bảng tiếp theo là một top-n loại:

select foo.* 
from foo 
join (select bar.* from bar group by bar.field) as bar on foo.field = bar.field 
where ... 
order by bar.field 
limit 10; 
0

lẽ bạn có thể xem xét sử dụng một Common Table Expression (CTE) thay vì một cái nhìn . Tôi có thể giúp làm cho truy vấn rõ ràng hơn theo cách tương tự để sử dụng chế độ xem, nhưng dường như không ảnh hưởng đến kế hoạch thực hiện theo cùng một cách.

Tôi đã gặp sự cố tương tự trong this question và sử dụng CTE thay vì chế độ xem đã thực hiện kế hoạch thực hiện hiệu quả hơn nhiều.

Các vấn đề liên quan