一尘不染

如何加快max()查询

sql

在PostgreSql 8.4查询中

explain analyze SELECT 
    max( kuupaev||kellaaeg ) as res
  from ALGSA 
  where laonr=1 and kuupaev <='9999-12-31' and 
     kuupaev||kellaaeg <= '9999-12-3123 59'

需要3秒钟来运行:

"Aggregate  (cost=3164.49..3164.50 rows=1 width=10) (actual time=2714.269..2714.270 rows=1 loops=1)"
"  ->  Seq Scan on algsa  (cost=0.00..3110.04 rows=21778 width=10) (actual time=0.105..1418.743 rows=70708 loops=1)"
"        Filter: ((kuupaev <= '9999-12-31'::date) AND (laonr = 1::numeric) AND ((kuupaev || (kellaaeg)::text) <= '9999-12-3123 59'::text))"
"Total runtime: 2714.363 ms"

如何在PostgreSQL
8.4.4中加快速度?表结构如下。algsa表在kuupaev上有索引,也许可以使用?或者可以更改查询以添加其他一些索引以使其快速。表中的现有列无法更改。

CREATE TABLE firma1.algsa
(
  id serial NOT NULL,
  laonr numeric(2,0),
  kuupaev date NOT NULL,
  kellaaeg character(5) NOT NULL DEFAULT ''::bpchar,
  ... other columns
  CONSTRAINT algsa_pkey PRIMARY KEY (id),
  CONSTRAINT algsa_id_check CHECK (id > 0)
)
);

CREATE INDEX algsa_kuupaev_idx  ON firma1.algsa  USING btree  (kuupaev);

更新

试过了 analyze verbose firma1.algsa;

INFO:  analyzing "firma1.algsa"
INFO:  "algsa": scanned 1640 of 1640 pages, containing 70708 live rows and 13 dead rows; 30000 rows in sample, 70708 estimated total rows
Query returned successfully with no result in 1185 ms.

但查询运行时间仍为2.7秒。

为什么有30000 rows in sample 。是不是太多了,应该减少吗?


阅读 132

收藏
2021-05-23

共1个答案

一尘不染

在旧版本的PostgreSQL中,这是一个已知的问题-
但它似乎已由8.4解决。实际上,针对8.0文档有一些警告,但针对8.1文档则没有。

因此,至少由于这个原因,您不需要升级主要版本。但是,您应该升级到当前的8.4系列版本8.4.16,因为您缺少数 的错误修复和调整价值。

真正的问题在于,您正在使用max表达式,而不是简单的值,并且该表达式没有功能索引。

您可以尝试在表达式上创建索引kuupaev||kellaaeg…但是我怀疑您有数据模型问题,并且通过修复数据模型还有更好的解决方案。

看起来kuupaev是kuup盲ev或日期,而kellaaeg可能是时间。如果是这样:永远不要使用concatenation(||)运算符组合日期和时间;使用间隔加法,例如kuupaev + kellaaeg。取而代之的是,char您应该使用数据类型timeinterval使用的CHECK约束kellaaeg,具体取决于数据类型的含义以及是否限制为24小时。或者,更好的是,使用单个类型的字段timestamp(对于本地时间)或timestamp with time zone(对于全球时间)来存储组合的日期和时间。

如果你这样做,你可以创建组合的列一个简单的索引取代了kellaaeg,并kuupaev和使用,对于minmax等等。如果你只需要日期部分或只是一些事情的时间部分,使用date_truncextractdate_part功能;

您仍然应该计划升级到9.2。从8.4升级到9.2的升级路径并不是很粗糙,您实际上只需要注意standard_conforming_strings默认情况下on的设置以及bytea_outputfromescape到to的更改hex。在过渡和移植过程中,两者都可以设置回8.4的默认值。8.4将不再受支持。

2021-05-23