2014-03-26 64 views
4

我有一個表PosgreSQL 9.1.9。有一個架構:如何防止更改執行計劃某些值

CREATE TABLE chpl_text 
(
    id integer NOT NULL DEFAULT nextval('chpl_text_id_seq1'::regclass), 
    page_id bigint NOT NULL, 
    page_idx integer NOT NULL, 
    ... 
); 

我在這張表中有大約40000000行(40M)。 現在,有一個查詢:

SELECT 
    ... 
FROM chpl_text 
ORDER BY id 
LIMIT 100000 
OFFSET N 

一切順利爲N <= 5300000。執行計劃看起來像這樣

Limit (cost=12743731.26..12984179.02 rows=100000 width=52) 
    -> Index Scan using chpl_text_pkey on chpl_text t (cost=0.00..96857560.86 rows=40282164 width=52) 

N >= 5400000奇蹟般地變成

Limit (cost=13042543.16..13042793.16 rows=100000 width=52) 
    -> Sort (cost=13029043.16..13129748.57 rows=40282164 width=52) 
     Sort Key: id 
     -> Seq Scan on chpl_text t (cost=0.00..1056505.64 rows=40282164 width=52) 

在很長的運行時間由此而來。

如何防止postresql更改更高偏移量的查詢計劃?

注意:我知道,大的補償不是很好,但我不得不在這裏使用它們。

+1

您使用的是默認配置值嗎?您應該嘗試增加work_mem和其他內存相關參數的大小。 –

+0

根據postgres DOC(http://www.postgresql.org/docs/9.1/static/sql-select.html#SQL-LIMIT),這是預期的。在這裏看到類似的帖子http://dba.stackexchange.com/questions/32956/execution-plan-in-simple-query-in-pgsql-depends-on-offset-clause-why。 – Rahul

+0

你可以用EXPLAIN(ANALYZE,BUFFERS)重複這些嗎? – jjanes

回答

1

如果Postgres的是體面配置中途,你的統計數據是最新的(ANALYZE或自動清理),成本設置健全,Postgres的一般都知道更好時候做索引掃描或順序掃描。詳細信息和鏈接:
Keep PostgreSQL from sometimes choosing a bad query plan

實際測試性能,而不順序掃描, 「禁用」 它(!在調試會話只)

SET enable_seqscan=OFF; 

More in the manual.

然後再次運行EXPLAIN ANALYZE ...另外,the release of Postgres 9.2 had a focus on "big data"。根據您的使用情況,您應該緊急考慮升級到current release

您也可以嘗試用CTE和row_number()替代查詢,看看查詢計劃原來更有利:

WITH cte AS (
    SELECT ..., row_number() OVER (ORDER BY id) AS rn 
    FROM chpl_text 
    ) 
SELECT ... 
FROM cte 
WHERE rn BETWEEN N+1 AND N+100000 
ORDER BY id; 

這並非總是如此,但可能會在你的特殊情況。