PostgreSQL - 未使用索引

时间:2014-04-16 13:30:46

标签: database postgresql

我创建了一个表。

我在更新另一个表时编写了更新表的过程。

也就是说,当我更新table2时,table2中的一些记录将使用我在table1创建的触发器更新为table2

我可以创建视图而不是这样做。但它的主要目的是我无法在视图上创建索引。

因此我确实喜欢这个。表2包含大约500k行。我正在更新大约220k行,并在某些计算中创建了一个额外的列,根据某些条件为每行提供01

我已经在table1上创建了一个索引。

如果我在count(*)中执行table2查询,其中我只有date col的一个索引。查询在200ms内执行,其行数约为500k。

但如果我在table1上执行相同的查询,那么与table2相比,它需要的时间加倍。

如果删除table1上的索引,则会在执行时间再添加500-600毫秒。

table1上创建索引刚刚减少了500-600ms

解释用2列分析查询。

"HashAggregate  (cost=80421.85..80422.94 rows=73 width=4) (actual time=6248.826..6248.829 rows=3 loops=1)"
"  ->  Seq Scan on table1  (cost=0.00..70306.88 rows=2022994 width=4) (actual time=0.048..4203.224 rows=2022994 loops=1)"
"        Filter: ((date >= '2014-02-01'::date) AND (date <= '2014-04-30'::date))"
"Total runtime: 6248.895 ms"

表定义:

CREATE TABLE table1
(
  label1 text NOT NULL,
  label2 text NOT NULL,
  label3 text NOT NULL,
  date date NOT NULL,
  "mobile no" bigint NOT NULL,
  "start time" time without time zone NOT NULL,
  "end time" time without time zone NOT NULL,
  label4 text NOT NULL,
  label5 text NOT NULL,
  value1 integer NOT NULL,
  count numeric NOT NULL
)

索引定义:

CREATE INDEX ix_date
  ON table1
USING btree
  (date);

我给出的COUNT(*)只是一个例子。

实际上,我通过将label1,2,3分组并从日期中提取月份来总结count列。

1 个答案:

答案 0 :(得分:0)

首先,

  

我可以创建视图而不是这样做。但它的主要目的是我无法在视图上创建索引。

视图已经扩展&#34;在处理查询时,例如SELECT x FROM my_view JOIN y...实际上会直接替换查询中的视图定义,如果适用,生成的扩展查询将能够直接使用任何索引。

其次,

  

如果我在table2中执行count(*)查询,其中我已经只有一个日期col的索引。查询在200ms内执行,其行数约为500k。

不幸的是,PostgreSQL中的COUNT(*)查询通常不使用索引,即使在最近的(9.2+)版本中也只使用索引扫描。请参阅此处:https://wiki.postgresql.org/wiki/Index-only_scans#Is_.22count.28.2A.29.22_much_faster_now.3F了解原因。非唯一(或主键)索引永远不会用于COUNT(*)

第三,更新MVRC数据库(如PostgreSQL)中的记录会创建这些记录的更新副本,而不是就地更新它们。这几乎总会导致严重的内部数据碎片,如果您使用寻道时间较慢的驱动器(如机械驱动器),则会非常明显。如果您希望在不同大小的表之间线性减少COUNT(*)次,请确保数据没有碎片(VACUUM FULL ANALYZE + REINDEX将主要执行此操作),或者只使用SSD。< / p>