修改 Postgres 9.0 查询计划

Posted

技术标签:

【中文标题】修改 Postgres 9.0 查询计划【英文标题】:Modify Postgres 9.0 query plan 【发布时间】:2012-02-24 10:14:47 【问题描述】:

我正在寻找有关如何修改 Postgres 9..0 查询计划的更多信息。

我有疑问:

SELECT
    max(creation_date) 
FROM 
    statistics_loged_users 
WHERE
    school_id    = 338 and 
    group_id     = 3 and 
    usr_id       = 243431;

并解释分析输出:

"Aggregate  (cost=1518.56..1518.57 rows=1 width=8) (actual time=410.459..410.459 rows=1 loops=1)"
"  ->  Bitmap Heap Scan on statistics_loged_users  (cost=993.96..1518.55 rows=1 width=8) (actual time=410.025..410.406 rows=210 loops=1)"
"        Recheck Cond: ((group_id = 3) AND (usr_id = 243431))"
"        Filter: (school_id = 338)"
"        ->  BitmapAnd  (cost=993.96..993.96 rows=133 width=0) (actual time=409.521..409.521 rows=0 loops=1)"
"              ->  Bitmap Index Scan on statistics_loged_users_idx2  (cost=0.00..496.85 rows=26669 width=0) (actual time=375.770..375.770 rows=3050697 loops=1)"
"                    Index Cond: (group_id = 3)"
"              ->  Bitmap Index Scan on statistics_loged_users_idx  (cost=0.00..496.85 rows=26669 width=0) (actual time=0.077..0.077 rows=210 loops=1)"
"                    Index Cond: (usr_id = 243431)"
"Total runtime: 411.419 ms"

我们可以看到第一个过滤器是按 group_id。 这张桌子非常非常大:) 因此有很多行 group_id 相同,但具有相同 usr_id 的行要少得多。

问题是我如何告诉查询计划第一个过滤器必须是 usr_id。

我在 group_id 和 usr_id 上创建索引并获得了性能, 但是我需要知道如何修改查询计划,这是为了将来:)

【问题讨论】:

估计行数 26,669,实际行数 3,050,697。我认为vacuum analyze 是正确的。你经常这样做吗? 【参考方案1】:

PostgreSQL 规划器并不真正以您想要的方式接受提示。实现您想要的最简单的方法是重写您的查询。

分析您的EXPLAIN ANALYZE 输出,很明显大部分时间都花在了以下部分:

" -> statistics_loged_users_idx2 上的位图索引扫描(成本=0.00..496.85 行=26669 宽度=0)(实际时间=375.770..375.770 行=3050697 循环=1)"

" 索引条件:(group_id = 3)"

如果您重写查询以便首先仅查找usr_idschool_id,您将得到您想要的。

SELECT
    max(creation_date) 
FROM 
(
    SELECT 
        group_id, creation_date
    FROM
        statistics_loged_users 
    WHERE
        school_id    = 338 and 
        usr_id       = 243431
) AS cd
WHERE 
group_id = 3;

【讨论】:

【参考方案2】:

当前查询现在必须使用两个索引,statistics_loged_users_idx 和 statistics_loged_users_idx2,单个索引可能更快。在 usr_id、group_id 和 school_id 上创建一个索引,并在索引中尝试其他一些列顺序。

两个例子:

CREATE INDEX idx_triple_index ON statistics_loged_users(usr_id, group_id, school_id);

CREATE INDEX idx_triple_2_index ON statistics_loged_users(usr_id, school_id, group_id);

试一试并再次检查 EXPLAIN ANALYZE。

【讨论】:

是的,这可以解决问题 - 获得更多性能 :) 但无论如何 - 有没有办法通过设置一些参数来修改计划如何执行查询。例如那里(每列都有索引,而不是单个索引)指定过滤器索引顺序?

以上是关于修改 Postgres 9.0 查询计划的主要内容,如果未能解决你的问题,请参考以下文章

posgresql

Postgresql 用户管理

Postgres 查询计划对于增加时间戳范围的查询有很大不同

在 postgres 中运行时查询计划更改

Postgres 不同的查询计划 Prod/QA

Postgres 不使用不同的查询计划来获得更高的偏移量