postgres:两个简单的,等效的查询,但一个慢得多

时间:2013-12-07 16:28:06

标签: sql postgresql

我在亚马逊EC2服务器上的ubuntu(12.04 LTS)上运行postgres(9.1)。我有这张桌子:

    Table "public.principal_component"
    Column     |       Type       | Modifiers 
---------------+------------------+-----------
eigenvalue_id  | integer          | not null
stm_id         | integer          | not null
value          | double precision |

Indexes:
    "principal_component_pk" PRIMARY KEY, btree (eigenvalue_id, stm_id)
"pc_eigval_index" btree (eigenvalue_id)
Foreign-key constraints:
    "principal_component_eigenvalue_id_fkey" FOREIGN KEY (eigenvalue_id) REFERENCES
         eigenvalue(id)
    "principal_component_stm_id_fkey" FOREIGN KEY (stm_id) REFERENCES stm(id)

编辑:此表包含69,789,400行。

我尝试运行此查询:

select count(*) from principal_component where eigenvalue_id >= 801 and 
    eigenvalue_id <= 900

但是我花了很长时间才取消了。所以我使用bash为上述查询中的每个id值运行查询:

time for ((a = 801; a <= 900; a++))
do 
    command="select count(*) from principal_component where eigenvalue_id=$a" 
    sudo -u postgres psql text_analytics -c "$command"`
done

并且这个bash命令总共需要16个(对于所有100个单独的查询以及显示等)。

然后我重新运行了第一个查询,并计时:它耗时250秒。

编辑:查询结果为0 - 计数为0(正如我预期的那样)

为什么会出现差异?以下是每个查询的解释计划结果: 快速,个人查询:

explain analyze select count(*) from principal_component where eigenvalue_id = 801"
                                     QUERY PLAN                                    
-----------------------------------------------------------------------------------
Aggregate  (cost=168209.10..168209.11 rows=1 width=0) (actual time=13.367..13.369 
    rows=1 loops=1)
->  Index Scan using pc_eigval_index on principal_component  (cost=0.00..167883.16
       rows=130377 width=0) (actual time=13.344..13.344 rows=0 loops=1)
         Index Cond: (eigenvalue_id = 801)
 Total runtime: 13.512 ms
(4 rows)

缓慢的“合并”查询:

explain analyze select count(*) from principal_component where eigenvalue_id >= 801 and
    eigenvalue_id <= 900"
                                    QUERY PLAN                                         
---------------------------------------------------------------------------------------
Aggregate  (cost=1618222.49..1618222.50 rows=1 width=0) (actual time=774.585..774.586
   rows=1 loops=1)
->  Bitmap Heap Scan on principal_component  (cost=656742.39..1560409.48 rows=23125206
   width=0) (actual time=774.558..774.558 rows=0 loops=1)
     Recheck Cond: ((eigenvalue_id >= 801) AND (eigenvalue_id <= 900))
     ->  Bitmap Index Scan on pc_eigval_index  (cost=0.00..650961.09 rows=23125206 
          width=0) (actual time=774.549..774.549 rows=0 loops=1)
           Index Cond: ((eigenvalue_id >= 801) AND (eigenvalue_id <= 900))
Total runtime: 774.751 ms
(6 rows)

我对阅读计划一无所知,所以我提前道歉,因为遗漏了一些明显的东西。提前感谢任何想法。

1 个答案:

答案 0 :(得分:1)

考虑在您的桌面上运行analyze,或者vacuum analyze如果它最近得到了大量更新,或者如果您已经这样做,则增加它正在收集的统计数量。 23M行的估计有点太多了。

除此之外,Postgres 9.1没有帮助。 9.2将进行仅索引扫描,从而消除过程中的位图索引扫描。

除此之外:查询不是严格等同或可比较的。第一个需要改为:

select count(*) from ... group by igenvalue_id