REINDEX危险吗?


17

我一直在尝试COUNT(*)使用包含主键的150,000行的表。它用了大约5分钟的时间,所以我发现这是一个索引问题。

引用PostgreSQL手册

REINDEX与删除索引和重新创建索引相似,因为索引内容是从头开始重建的。但是,锁定注意事项却大不相同。REINDEX锁定对索引的父表的写入但不对其进行读取。它还对正在处理的特定索引采取排他锁,这将阻止尝试使用该索引的读取(...)。后续的CREATE INDEX锁定写入但不读取;由于索引不存在,因此不会进行任何读取尝试,这意味着将不存在阻塞,但可能会将读取强制进行昂贵的顺序扫描。

根据您自己的经验,您能否告诉您:

  • REINDEXING危险吗?会损害数据一致性吗?
  • 会花费很多时间吗?
  • 这是我的情况的可能解决方案吗?

更新:

对我们有用的解决方案是使用不同的名称重新创建相同的索引,然后删除旧索引。

索引创建非常快,我们将索引大小从650 MB减小到8 MB。使用COUNT(*)with between只需3秒。

Answers:


15

重新索引不是危险的,也不会损害数据一致性。但是,如果您有时间紧迫的写操作,则在表被锁定且DML中止的情况下,可能会丢失数据。

重新索引应该不会花费很多时间,但是通常会涉及读取整个表,对索引字段进行排序以及编写新索引。给定时间,COUNT(*)可能需要五分钟或更长时间。

这不太可能是索引问题。 COUNT(*)应该使用表扫描,在这种情况下不读取索引。我希望您遇到某种IO问题。

尝试使用COUNT(1)COUNT(pk_field)可能使用索引的索引。

如果您在Unix或Linux平台上运行,则可能需要使用监视磁盘活动sar。您可能还拥有发生故障的磁盘,可以大大降低IO速率。

具有大对象的表还可以显着增加IO,以构造COUNT(*)的记录。


2
根据wiki.postgresql.org,COUNT(*)是最佳选择:If you are using count(*), the database is free to use any column to count, which means it can pick the smallest covering index to scan (note that this is why count(*) is much better than count(some_field), as long as you don't care if null values of some_field are counted). Since indexes often fit entirely in memory, this means count(*) is often very fast.
orange80

1

我不确定最适合您的答案。但是,该线程似乎提供了一些好的建议: http://postgresql.1045698.n5.nabble.com/count-performance-issue-td2067873.html

需要注意的是,您可以实现TRIGGER来在单独的表中维护行数(如果COUNT(*)被应用程序频繁调用)。

一些答复表明,这是最近没有足够清理的数据库的症状(建议您在服务器上或特别是对该数据库禁用自动清理)?

另一个建议如下:

ANALYZE tablename;
SELECT reltuple FROM pg_class WHERE relname = 'tablename';

识别为A. Kretschmer的人指出:

否。当前索引实现不包含有关当前事务中行可见性的信息。您需要扫描整个数据表,以获取当前行在当前事务中是否可见。

...支持我关于行级权限是性能方面的意见。

我的搜索还显示了WikiVS:MySQL与PostgreSQL:COUNT(*)

您可以细读我使用Google发现的其他结果:postgresql count(*)性能

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.