【发布时间】:2016-12-23 16:17:29
【问题描述】:
我有一个相对较大的表(大约一百万条记录),包含以下列:
- 帐户:字符变化 (36) 不为空
- 组:字符变化(255)不为空
- 分类:字符变化(255)不为空
- 大小:整数不为空
该帐户实际上是一个 UUID,但我认为这并不重要。如果我执行以下简单查询,我的机器上大约需要 16 秒:
select account, group, classification, max(size)
from mytable
group by account, group, classification
到目前为止一切顺利。假设我添加一个索引:
CREATE INDEX concurrently ON mytable (account, group, classification);
如果我再次执行相同的查询,它现在会在不到半秒的时间内返回结果。解释查询也清楚地表明使用了索引。
但是,如果我将查询改写为
select account, group, classification, max(size)
from mytable
group by account, classification, group
再次需要 16 秒,索引不再使用。在我看来,分组标准的顺序并不重要,但我不是专家。知道为什么 Postgresql 不能(或不能)优化后一个查询。我在 Postgresql 9.4 中试过这个
编辑:根据要求,这里是解释的输出。对于索引调用:
Group (cost=0.55..133878.11 rows=95152 width=76) (actual time=0.090..660.739 rows=807 loops=1)
Group Key: group_id, classification_id, account_id
-> Index Only Scan using mytable_group_id_classification_id_account_id_idx on mytable (cost=0.55..126741.72 rows=951518 width=76) (actual time=0.088..534.645 rows=951518 loops=1)
Heap Fetches: 951518
Planning time: 0.106 ms
Execution time: 660.852 ms
对于groupby条件顺序改变的调用:
Group (cost=162327.31..171842.49 rows=95152 width=76) (actual time=11114.130..13938.487 rows=807 loops=1)"
Group Key: group_id, account_id, classification_id
-> Sort (cost=162327.31..164706.10 rows=951518 width=76) (actual time=11114.127..13775.235 rows=951518 loops=1)
Sort Key: group_id, account_id, classification_id
Sort Method: external merge Disk: 81136kB
-> Seq Scan on mytable (cost=0.00..25562.18 rows=951518 width=76) (actual time=0.009..192.259 rows=951518 loops=1)
Planning time: 0.111 ms
Execution time: 13948.380 ms
【问题讨论】:
-
请edit 您的问题并为这两种情况添加
explain (analyze)的输出。 Formatted 请发短信,no screen shots 另外:您尝试过更新的 Postgres 版本吗?在 9.5 和 9.6 中,特别是在聚合方面有一些增强 -
好吧,我认为顺序确实很重要,因为分组会向下滚动列表 - 意思是找到 1.grouped 列的所有值,并为每个值查找 2.grouped 列等的所有值。这与索引的组织方式相同。所以如果索引覆盖了同一个订单计划器中的所有列,可以直接使用它。但是,如果您按计划者对分组中的列重新排序,则不能使用具有不同列顺序的索引。
-
@a_horse_with_no_name 我还没有尝试过 postgresql 9.6 来查看是否有不同的行为。
标签: postgresql indexing group-by