我的表'日志'有大约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
答案 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太旧了,您无法使用该功能。