使用SUM的PostgreSQL查询需要很长时间才能执行

时间:2015-10-22 00:08:06

标签: postgresql

我的表'日志'有大约2500万行(并且每天都在增长),我的查询需要大约10秒才能执行。

我使用的是Debian Linux和PostgreSQL 9.1。

-- Table: logs

CREATE TABLE logs
(
  ad_id character(24),
  id serial NOT NULL,
  created_at timestamp without time zone,
  campaign_id character(24),
  zone character(50),
  request_url character(500),
  click smallint DEFAULT 0,
  impression smallint DEFAULT 0,
  view smallint DEFAULT 0,
  CONSTRAINT logs_pkey PRIMARY KEY (id)
);

CREATE INDEX index_ad_id
  ON logs
  USING btree
  (ad_id COLLATE pg_catalog."default");

CREATE INDEX index_campaign_id
  ON logs
  USING btree
  (campaign_id COLLATE pg_catalog."default");

正如您所看到的,我已经在ad_id和campaign_id上创建了索引,并且在执行下面提到的查询时没有明显的速度差异。

select sum(click) as click, sum(impression) as impression
from logs
where campaign_id='561b9a248280de632f207e5d'
  and created_at > '2015-10-01 00:00';

在对这类数据进行此类查询时是否有任何技巧。

目前我在Memcached中缓存结果以加快服务数据的速度,但由于现在需要在当前状态下实时显示这些数据,因此应用程序的响应性很差。

我最初使用的是InfluxDB,但与PostgreSQL相比,性能非常糟糕。

我遵循了加速PostgreSQL服务器的指导原则,但没有任何积极的变化。

任何建议都将不胜感激。

explain select sum(click) as click, sum(impression) as impression from logs where ad_id='5602609e8280de4d9a1d8bb8' and created_at > '2015-10-01 00:00';
                                       QUERY PLAN                                       
----------------------------------------------------------------------------------------
 Aggregate  (cost=697098.52..697098.53 rows=1 width=4)
   ->  Index Scan using index_ad_id on logs  (cost=0.56..695875.68 rows=244568 width=4)
         Index Cond: (ad_id = '5602609e8280de4d9a1d8bb8'::bpchar)
         Filter: (created_at > '2015-10-01 00:00:00'::timestamp without time zone)
(4 rows)

Time: 0.645 ms

1 个答案:

答案 0 :(得分:0)

(campaign_id, created_at)上的复合索引而不是单独的索引可能很有用。

您可能应该使用"C"归类作为列进行更快速的比较,因为您不需要本地化归类。

此外,以某些插入性能为代价,您可以尝试创建一个涵盖所有相关列的索引,以允许仅索引扫描。

这就是我要做的事情:

CREATE INDEX whatever ON logs (
    campaign_id COLLATE "C",
    created_at,
    click,
    impression
);

然后查询:

....
campaign_id = '561b9a248280de632f207e5d' COLLATE "C"
....

如果您收到关于COLLATE "C"的语法错误,那么您的PostgreSQL太旧了,您无法使用该功能。