2010-08-19 18 views
5

Postgres 8.4'te yaklaşık 5 saniye içinde çalışan bir sorgum var. Diğer tablolara eklenen bir görünümden veri seçer, ancak gecikme() pencere işlevini de kullanır. Encapsulating Postgres sorgu görünümünde görünümü son derece yavaşlatıyor

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

kolaylık sağlamak için diğer eskisi gibi JOIN ve filtreler tüm kullanarak, basitçe

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

sahiptir ve daha sonra bundan SEÇ yeni bir görünüm yarattı. Benim sürprizime bu sorgu 12 dakika içinde tamamlanmaz (ben o noktada durdu). Açıkçası Postgres, farklı bir yürütme planı seçti. Bunu yapmamak için nasıl yaparım? Orijinal plandaki gibi aynı planı kullanmak? Bir görüşün yürütme planını değiştirmemesi gerektiğini düşünürdüm ama görünüşe göre öyle.

Düzenleme: Dahası, ilk görünümün içeriğini kopyaladığım halde hala dönmemesi gerektiğini buldum.

Düzenleme 2: Tamam, sorguları göndermek için sorguyu sadeleştirdim.

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) 

(bu anında döner) görüntü dışında pencere fonksiyonunu alarak ve sorguda kendisine koyarak: görünümü (bu herhangi makul bir süre içinde iade etmez) kullanarak

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)) 

yüzden yavaş durumunda ilk tüm verilere pencere fonksiyonu uygulamak ve daha sonra muhtemelen konu olan filtrelemek çalışıyor gibi görünüyor. Bunu neden yaptığını bilmiyorum.

+0

+1, ancak birilerinin neler olup bittiğini teşhis edebilmesinden önce '' 'parçalarını doldurmanız gerekeceğinden şüpheleniyorum. – Edmund

+0

Yapabilirim, ancak eğer oldukça karmaşık bir tablo varsa ve tüm ilgili tabloların neye benzediğini açıklamak zorundayım. Benim sorum bu daha ziyade bu özel sorgu için genel bir çözüm hakkında daha fazla: Postgres'e bir görünümü "gözden geçirmesi" ve aynı SQL planını doğrudan temelde SQL'e girmiş gibi kullanmasını söylemenin bir yolu var. – EMP

+1

Sorgu yürütme planlarını yayınlama? EXPLAIN SELECT ... –

cevap

2

İki plan arasındaki farkınız, bir birleştirme ile birleşmekten geliyor. Bu, yuvalanmış bir döngü planı kullanılmasını engeller. Topluluğunuzu görüşünüzde kullandığınızda, kendinizi bu olumsuz senaryoya sokarsınız.

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

Belki bir bakış yerine Common Table Expression (CTE) kullanarak düşünebiliriz:

Bu, örneğin, hemen hemen her zaman bir üst-n tür ardından iki tablo üzerinde bir birleştirme veya karma katılmak planına yol açacaktır . Sorguyu, bir görünüm kullanmanın benzeri bir yolla yapmanıza yardımcı olabilirim, ancak yürütme planını da aynı şekilde etkilemiyor gibi görünmüyor.

this question'da benzer bir sorun yaşadım ve bir görünüm yerine CTE kullanmak, yürütme planını çok daha verimli hale getirdi.

İlgili konular