PostgreSQL 9.4
我有下表stat
:
user_id registration_date operator_id value
integer timestamp without time zone integer
该表约为22M行。我需要执行以下查询:
SELECT user_id, operator_id, COUNT(DISTINCT value)
WHERE registration_date > '2011-11-11 0:0:0'
AND registration_date < '2011-12-11 0:0:0'
GROUP BY user_id, operator_id
间隔很短。所以,我试图在日期创建索引
CREATE INDEX ON stat(date, user_id, operator_id)
和
CREATE INDEX ON stat(user_id, operator_id, date)
但它们不用于排序。计划:
GroupAggregate (cost=5376.49..5406.24 rows=1 width=21)
Group Key: user_id, operator_id
-> Sort (cost=5376.49..5383.92 rows=2974 width=21)
Sort Key: partner_id, platform_id
-> Index Scan using idx on stat (cost=0.43..5204.91 rows=2974 width=21)
Index Cond: ((registration_date > '2011-11-11 0:0:0'::timestamp without time zone) AND (registration_date < '2011-12-11 0:0:0'::timestamp without time zone))
我应该创建什么样的零件才能使用索引进行排序和搜索?
答案 0 :(得分:1)
使用查询结构,我认为您不能对WHERE
和GROUP BY
使用简单索引。 WHERE
中的不等式阻止了这一点。
如果您通常关注从第11天开始的月份,那么一个解决方案将是表达式的索引。像这样:
create index . . . on stat((date_trunc(registration_date - interval '10 day'),
'month'), user_id, operator_id)
表达式计算日期的年 - 月,假设月份从11日开始。
然后,您可以在查询中使用相同的表达式:
SELECT user_id, operator_id, COUNT(DISTINCT value)
WHERE date_trunc(registration_date - interval '10 day', 'month') = '2011-11-01'
GROUP BY user_id, operator_id;
这至少可以利用查询的索引。我并不是100%确定Postgres会实际使用索引(值得测试)。
注意:您可能希望在索引中包含value
。有些数据库也会使用count(distinct)
的索引;再一次,我不确定Postgres是否会在这种情况下。