【问题标题】:Postgres where query optimizationPostgres where 查询优化
【发布时间】:2015-09-13 09:23:48
【问题描述】:

在我们的数据库中,我们有一个表 menus 有 515502 行。它有一列status,其类型为smallint

目前,对于具有 status3 的一组文档,一个简单的计数查询需要 700 毫秒。

explain analyze select count(id) from menus where status = 2;
Aggregate  (cost=72973.71..72973.72 rows=1 width=4) (actual time=692.564..692.565 rows=1 loops=1)
->  Bitmap Heap Scan on menus  (cost=2510.63..72638.80 rows=133962 width=4) (actual time=28.179..623.077 rows=135429 loops=1)
         Recheck Cond: (status = 2)
         Rows Removed by Index Recheck: 199654
         ->  Bitmap Index Scan on menus_status  (cost=0.00..2477.14 rows=133962 width=0) (actual time=26.211..26.211 rows=135429 loops=1)
               Index Cond: (status = 2)
 Total runtime: 692.705 ms
(7 rows)

某些行的列值为 1,查询运行速度非常快。

 explain analyze select count(id) from menus where status = 4;
                                                          QUERY PLAN                                                           
-------------------------------------------------------------------------------------------------------------------------------
 Aggregate  (cost=7198.73..7198.74 rows=1 width=4) (actual time=24.926..24.926 rows=1 loops=1)
   ->  Bitmap Heap Scan on menus  (cost=40.53..7193.53 rows=2079 width=4) (actual time=1.461..23.418 rows=2220 loops=1)
         Recheck Cond: (status = 4)
         ->  Bitmap Index Scan on menus_status  (cost=0.00..40.02 rows=2079 width=0) (actual time=0.858..0.858 rows=2220 loops=1)
               Index Cond: (status = 4)
 Total runtime: 25.089 ms
(6 rows)

我观察到最通用的btree 索引是基于简单等式查询的最佳索引策略。 ginhash 都比 btree 慢。

对于使用索引的任何过滤器更快地进行count 查询的任何提示?

我知道这是一个初学者级别的问题,所以对于我可能犯的任何错误,请提前道歉。

【问题讨论】:

  • 如果你有一张大表并且索引使用率很好,你可以尝试优化过程。我的意思是:状态会经常变化吗?你能准备一张准备好总和的表格,并用触发器或函数来维护它吗?
  • id 是这个表的主键吗?你可以试试count(*) 吗?
  • 好的,所以如果查询和索引合适,您应该能够从仅索引扫描(自 9.2 起)中受益,这是我想知道版本的主要原因。
  • @user2512324 count(status) 也应该可以工作。 count(id) 没有的原因是 PostgreSQL 没有通过证明 idNOT NULL 来优化 count(id) 以等效于 count(1),所以它认为它必须获取 id 字段,它不是索引的一部分,因此无法使用仅索引扫描获取。
  • 如果您需要超快的速度,您可能需要考虑使用触发器或定期刷新的触发器来维护物化视图。请注意,触发器维护的 mat 视图往往会影响插入/更新/删除的并发性,并且定期更新的 mat 视图不会完全准确。

标签: sql postgresql indexing


【解决方案1】:

也许您的表中 status = 2 的行多于 status = 4 的行,因此,对于第二种情况,总表访问时间更长。 因此,对于status = 2,需要考虑的行太多,因此Bitmap Heap Scan的Bitmap进入“有损”模式,操作后需要重新检查。所以,有两件事需要考虑:要么你的结果太大(但是如果不重新组织你的表,你就不能做任何事情,比如分区),或者你的 'work_mem' 参数是太小而无法保持间歇性结果。如果有可能,尝试增加它的价值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-10-12
    • 2022-01-24
    • 2011-02-13
    • 1970-01-01
    • 1970-01-01
    • 2017-07-19
    • 2020-03-19
    相关资源
    最近更新 更多