我有一个表,该表具有三列A,B,C,均为bytea
类型。
表中大约有180,000,000行。 A,B和C都有正好20个字节的数据,C有时包含NULL
使用
为所有列创建索引时CREATE INDEX index_A ON transactions USING hash (A);
CREATE INDEX index_B ON transactions USING hash (B);
CREATE INDEX index_C ON transactions USING hash (C);
index_A在大约10分钟内创建,而B和C花费了10多个小时,之后我中止了它们。我自己运行每个CREATE INDEX,因此没有并行创建任何索引。数据库中也没有其他查询在运行。 运行时
SELECT * FROM pg_stat_activity;
wait_event_type
和wait_event
均为NULL,state
是 active 。
为什么第二个索引创建需要这么长时间,我可以做些什么来加快它们的速度?
答案 0 :(得分:1)
确保表格上的统计信息是最新的。
然后执行以下查询:
SELECT attname, n_distinct, correlation
from pg_stats
where tablename = '<Your table name here>'
基本上,在以下情况下,数据库将有更多工作来创建索引:
我怀疑您会发现字段A在不同值和/或更高的correlation方面与其他2个字段有所不同。
编辑:基本上,创建表的索引= FULL SCAN
,并在进行过程中在索引中创建条目。您在下面共享的统计信息意味着:
abs(correlation)
非常低。FULL SCAN
。注意:简化描述以突出区别。
解决方案1 :
不要为B和C创建索引。
听起来可能很愚蠢,但实际上,正如here所述,较小的相关性意味着可能不会使用索引(仅当条目未分散在所有表块中时,索引才有用)。
解决方案2 :
订购磁盘上的记录。
初始化将是这样的:
CREATE TABLE Transactions_order as SELECT * FROM Transactions;
TRUNCATE TABLE Transactions;
INSERT INTO Transactions SELECT * FROM Transactions_order ORDER BY B,C,A;
DROP TABLE Transactions_order;
接下来是棘手的部分:使用插入/更新/删除记录,您需要跟踪相关性并确保相关性不会下降太多。
如果不能保证,请遵循解决方案1。
解决方案3 :
创建partitions并享受分区修剪的功能。
最近在postgresql中进行了大量的分区工作。值得一看。