Postgresql查询很慢
Posted
技术标签:
【中文标题】Postgresql查询很慢【英文标题】:Postgresql very slow query 【发布时间】:2013-03-20 22:20:01 【问题描述】:这个查询运行很慢。为什么?其他都很好。我认为索引很好。
explain analyze
select "e_inst"."si_id" as "c0"
from "e_inst" as "e_inst"
group by "e_inst"."si_id"
order by "e_inst"."si_id" ASC NULLS LAST
查询计划:
Sort (cost=12221.87..12221.90 rows=68 width=4) (actual time=1115.377..1115.433 rows=81 loops=1)
Sort Key: si_id
Sort Method: quicksort Memory: 28kB
-> HashAggregate (cost=12221.25..12221.45 rows=68 width=4) (actual time=1115.198..1115.261 rows=81 loops=1)
-> Seq Scan on e_inst (cost=0.00..11920.07 rows=602357 width=4) (actual time=0.021..611.570 rows=602357 loops=1)
Total runtime: 1115.538 ms
创建表和索引:
CREATE TABLE e_inst (
id integer NOT NULL,
ip numeric,
gu character varying,
referrer character varying,
proc integer,
loke_id integer,
top_id integer,
si_id integer,
kop integer,
count integer,
created integer,
modified integer,
timepop integer,
count_active character varying,
country character(3),
info character varying
);
CREATE INDEX "topEnhance" ON e_inst USING btree (created, top_id);
CREATE INDEX "procEnhance" ON e_inst USING btree (created, proc);
CREATE INDEX "countryEnhance" ON e_install USING btree (created, country);
CREATE INDEX "createdE" ON e_inst USING btree (created);
ALTER TABLE e_inst CLUSTER ON "createdE";
CREATE INDEX "lokeE" ON e_inst USING btree (loke_id);
CREATE INDEX "lokeEnhance" ON e_inst USING btree (created, loke_id);
CREATE INDEX "siE" ON e_inst USING btree (si_id);
CREATE INDEX "siEnhance" ON e_inst USING btree (created, si_id);
CREATE INDEX "kopEnhance" ON e_inst USING btree (created, kop);
【问题讨论】:
旁白:如果索引数据的基数不高,索引将无济于事。 对不起PGSQL菜鸟,什么是高基数? 因为人群比我解释得更好:en.wikipedia.org/wiki/Cardinality_(SQL_statements) 您使用的是哪个 Postgres 版本? 9.2 可能会进行仅索引扫描,这可能会使事情变得更快。"e_inst"
和 e_install
实际上是同一个东西,只是在你的问题中伪装?如果是,请修复您的问题。无论哪种方式,升级到 9.2 都会提高性能,这种情况肯定可以从 index-only scan 中获益。但在 9.1 中也不应该那么慢......
【参考方案1】:
处理整个表的查询不会使用索引。
事实上,您正在检索和处理 600k 条记录。它在短短一秒钟内就完成了这一点,这确实令人印象深刻。
现在在这种情况下,您尝试从 600k 记录中提取 81 个不同的值。您可能想要做的是构造一个递归查询,以便它获取一行 81 次。这可能会更快,但不能保证。通常我在返回的行数少得多的地方使用这些。但是这里是一个例子:
WITH RECURSIVE sparse_scan AS (
SELECT min(si_id) as si_id FROM e_inst
UNION ALL
SELECT min(si_id) as si_id
FROM e_inst
JOIN (select max(si_id) as last FROM sparse_scan) s
WHERE s.last < si_id
)
SELECT si_id as c0 FROM sparse_scan;
请注意,这会将顺序扫描替换为 81 次索引扫描。
【讨论】:
我想这样做,但我无法更改查询,因为 Mondrian 构建了我的查询。【参考方案2】:升级到 PostgreSQL 9.2。现在是仅索引扫描! 效果很好,感谢 a_horse_with_no_name 建议我升级。
【讨论】:
以上是关于Postgresql查询很慢的主要内容,如果未能解决你的问题,请参考以下文章