相同的postgres查询在不同的数据库中生成不同的查询计划

时间:2014-03-29 08:08:55

标签: postgresql indexing

posgtres版本9.1.9

以下查询在两个不同的数据库中运行时会生成不同的计划。

explain (analyze,buffers) SELECT group_.groupid     AS groupId,
        group_.name        AS groupName,
        group_.type_       AS groupType,
        group_.friendlyurl AS groupFriendlyURL
 FROM   group_
        inner join groups_orgs
                ON ( groups_orgs.groupid = group_.groupid )
        inner join users_orgs
                ON ( users_orgs.organizationid = groups_orgs.organizationid )
 WHERE  ( group_.livegroupid = 0 )
        AND ( users_orgs.userid = '27091470' )
        AND ( group_.companyid = '20002' )
        AND ( group_.classnameid = 10001
               OR group_.classnameid = 10003 )
        AND ( group_.name != 'Control Panel' )
        AND ( group_.type_ != 4 )
;

从生产数据库计划。

                                                                                      QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Merge Join  (cost=6.36..16.60 rows=1 width=37) (actual time=0.133..95.323 rows=3 loops=1)
   Merge Cond: (group_.groupid = groups_orgs.groupid)
   Buffers: shared hit=30829
   ->  Index Scan using group__pkey on group_  (cost=0.00..87997.62 rows=17244 width=37) (actual time=0.030..85.166 rows=13906 loops=1)
         Filter: (((name)::text <> 'Control Panel'::text) AND (type_ <> 4) AND (livegroupid = 0) AND (companyid = 20002::bigint) AND ((classnameid = 10001) OR (classnameid = 10003)))
         Buffers: shared hit=30824
   ->  Sort  (cost=6.36..6.37 rows=3 width=8) (actual time=0.076..0.079 rows=3 loops=1)
         Sort Key: groups_orgs.groupid
         Sort Method: quicksort  Memory: 25kB
         Buffers: shared hit=5
         ->  Merge Join  (cost=1.05..6.34 rows=3 width=8) (actual time=0.045..0.054 rows=3 loops=1)
               Merge Cond: (users_orgs.organizationid = groups_orgs.organizationid)
               Buffers: shared hit=5
               ->  Index Scan using users_orgs_pkey on users_orgs  (cost=0.00..10.47 rows=2 width=8) (actual time=0.012..0.014 rows=2 loops=1)
                     Index Cond: (userid = 27091470::bigint)
                     Buffers: shared hit=4
               ->  Sort  (cost=1.05..1.06 rows=3 width=16) (actual time=0.028..0.030 rows=3 loops=1)
                     Sort Key: groups_orgs.organizationid
                     Sort Method: quicksort  Memory: 25kB
                     Buffers: shared hit=1
                     ->  Seq Scan on groups_orgs  (cost=0.00..1.03 rows=3 width=16) (actual time=0.003..0.005 rows=3 loops=1)
                           Buffers: shared hit=1

从数据库计划,该数据​​库是通过从生产

导出/导入数据创建的
                                                                                      QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Nested Loop  (cost=0.00..18.19 rows=1 width=36) (actual time=0.053..0.104 rows=3 loops=1)
   Buffers: shared hit=18
   ->  Nested Loop  (cost=0.00..9.77 rows=1 width=8) (actual time=0.036..0.065 rows=3 loops=1)
         Join Filter: (groups_orgs.organizationid = users_orgs.organizationid)
         Buffers: shared hit=6
         ->  Seq Scan on groups_orgs  (cost=0.00..1.03 rows=3 width=16) (actual time=0.007..0.010 rows=3 loops=1)
               Buffers: shared hit=1
         ->  Materialize  (cost=0.00..8.66 rows=2 width=8) (actual time=0.008..0.012 rows=3 loops=3)
               Buffers: shared hit=5
               ->  Index Scan using ix_fb646ca6 on users_orgs  (cost=0.00..8.65 rows=2 width=8) (actual time=0.016..0.021 rows=3 loops=1)
                     Index Cond: (userid = 27091470::bigint)
                     Buffers: shared hit=5
   ->  Index Scan using group__pkey on group_  (cost=0.00..8.41 rows=1 width=36) (actual time=0.008..0.010 rows=1 loops=3)
         Index Cond: (groupid = groups_orgs.groupid)
         Filter: (((name)::text <> 'Control Panel'::text) AND (type_ <> 4) AND (livegroupid = 0) AND (companyid = 20002::bigint) AND ((classnameid = 10001) OR (classnameid = 10003)))
         Buffers: shared hit=12

生产查询大约需要100毫秒,而其他数据库需要0.1毫秒 差异似乎是group_表(Index Scan using group__pkey on group_)上的慢速索引扫描 任何人都可以解释执行时间的差异吗? 生产中的表定期进行抽真空和分析。 生产数据库比其他数据库更繁忙。

谢谢, 萨米尔

1 个答案:

答案 0 :(得分:4)

我遇到了同样的问题,在“备份”数据库中,查询速度非常快,而且在生产数据库中运行时相同的查询速度非常慢。事实证明,我只需更频繁地执行Routine Database Maintenance Tasks来解决问题:

  

PostgreSQL查询规划器依赖于有关表内容的统计信息,以便为查询生成良好的计划。这些统计信息由ANALYZE命令收集,该命令可以单独调用,也可以作为VACUUM中的可选步骤调用。拥有合理准确的统计数据非常重要,否则糟糕的计划选择可能会降低数据库性能。

因此,如果您遇到类似问题,请尝试在“慢”数据库上运行以下命令:

$ vacuumdb --host localhost --port 5432 --username "MyUser" -d "MyDatabase" --analyze --verbose