真正长时间运行查询时使用order by

时间:2011-03-22 14:24:46

标签: postgresql

我的一个查询存在一个主要问题:

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

2 个答案:

答案 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。