我应该创建什么索引来使用ir进行搜索和排序?

时间:2016-01-11 14:46:06

标签: sql postgresql indexing

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))

我应该创建什么样的零件才能使用索引进行排序和搜索?

1 个答案:

答案 0 :(得分:1)

使用查询结构,我认为您不能对WHEREGROUP 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是否会在这种情况下。