我的一个查询存在一个主要问题:
SELECT tpostime, gispoint
FROM mytable
WHERE idterminal = 233463
ORDER BY idpos DESC
当'mytable'中不存在idterminal时,此查询将被永久处理,然后我会看到超时(由于用户请求'消息声明'特定的消息),但当我删除订单时一句话,一切似乎都很好。现在我想知道 - idpos是'mytable'的主键,因此它被索引,所以它的排序应该很快,我猜。 重要的是 - 'mytable'重量为3gb。
表和索引定义:
CREATE TABLE mytable (
idpos serial NOT NULL,
tpostime timestamp(0) without time zone,
idterminal integer DEFAULT 0,
gispoint geometry,
idtracks integer,
CONSTRAINT mytable_pkey PRIMARY KEY (idpos),
CONSTRAINT qwe FOREIGN KEY (idtracks) REFERENCES qwe (idtracks)
MATCH SIMPLE ON UPDATE NO ACTION ON DELETE CASCADE,
CONSTRAINT abc FOREIGN KEY (idterminal) REFERENCES abc (idterminal)
MATCH SIMPLE ON UPDATE NO ACTION ON DELETE CASCADE,
CONSTRAINT enforce_geotype_gispoint
CHECK (geometrytype(gispoint)= 'POINT'::text OR gispoint IS NULL),
CONSTRAINT enforce_srid_gispoint CHECK (srid(gispoint) = 4326)
) WITH OIDS;
CREATE INDEX idx_idterminal ON mytable USING btree (idterminal);
CREATE INDEX idx_idtracks ON mytable USING btree (idtracks);
CREATE INDEX idx_idtracks_idterminal ON mytable USING btree (idtracks, idterminal);
答案 0 :(得分:5)
在我看来,idterminal的选择性足够低,以便postgres选择mytable_pkey
的完整扫描,而不是使用idterminal = 233463
我建议:
CREATE INDEX idx_idterminal2 ON mytable USING btree (idterminal, idpos);
或许:
DROP INDEX idx_idterminal;
您没有提及这是否是生产数据库 - 如果您当然需要先在其他地方测试更改的影响。
如果您不想更改架构,您可能会尝试将优化器引入您认为最适合8.4(及以上)的(未经测试)的路径:
SELECT *
FROM ( SELECT tpostime, gispoint, idpos, row_number() over (order by 1)
FROM mytable
WHERE idterminal = 233463 )
ORDER BY idpos DESC;
或者只是:
SELECT *
FROM ( SELECT tpostime, gispoint, idpos
FROM mytable
WHERE idterminal = 233463
GROUP BY tpostime, gispoint, idpos )
ORDER BY idpos DESC;
甚至:
SELECT tpostime, gispoint
FROM mytable
WHERE idterminal = 233463
ORDER BY idpos*2 DESC
答案 1 :(得分:0)
你有关于idterminal的索引吗?尝试添加复合索引(idpos,idterminal)。如果你做解释计划可能会发生什么,是先按idpos排序,然后扫描找到idterminal。