桌子上有几个索引.如果我不删除并重新创建索引,我是否需要在每次截断和重新填充后重新索引,或者这是不必要的?我应该在TRUNCATE之后运行VACUUM,还是不必要?
它有点类似于this answer about cluster – Pg在TRUNCATE期间自动丢弃索引,然后在插入数据时逐步重建它,因此在TRUNCATE之前没有保持索引膨胀.
如果删除索引,截断,插入数据和重新创建索引,则可能会获得更紧凑和高效的索引.他们肯定会更快建立.一旦构建,索引性能的差异就不足以保证大多数应用程序仅使用b-tree索引的额外工作,但填充表所需的时间差异非常值得.如果您正在使用GiST或(特别是)GIN,最好删除索引并在最后重新创建.
如果这样做很方便,请删除索引并在最后添加它们,如果这对您不实用,请不要太担心.
对于我测试中的常规b树,增量创建的复合索引为3720kb,而一次性创建的索引为2208kb.构建时间为164ms(插入)347ms(索引)对比742ms(插入索引).这种差异很大,但不足以成为一个巨大的问题,除非你做大规模的DW.插入索引运行后,REINDEX再花了342ms.看到
因此,@TomTom是正确的(不足为奇),因为如果方便的话,可以放弃并重新创建索引,就像你为OLAP工作大量填充表一样.
但是,重建索引很可能是错误的答案,因为这意味着你要做一大堆昂贵的工作来创建一个你扔掉的索引.删除索引并重新创建它而不是重新索引.
演示会:
regress=# -- Create,populate,then create indexes: regress=# CREATE TABLE demo (someint integer,sometext text); CREATE TABLE regress=# \timing on regress=# INSERT INTO demo (someint,sometext) SELECT x,(x%100)::text FROM generate_series(1,100000) x; INSERT 0 100000 Time: 164.678 ms regress=# CREATE INDEX composite_idx ON demo(sometext,someint); CREATE INDEX Time: 347.958 ms regress=# SELECT pg_size_pretty(pg_indexes_size('demo'::regclass)); pg_size_pretty ---------------- 2208 kB (1 row) regress=# -- Total time: 347.958+164.678=512.636ms,index size 2208kB regress=# -- Now,with truncate and insert: regress=# TRUNCATE TABLE demo; TRUNCATE TABLE regress=# INSERT INTO demo (someint,100000) x; INSERT 0 100000 Time: 742.813 ms regress=# SELECT pg_size_pretty(pg_indexes_size('demo'::regclass)); pg_size_pretty ---------------- 3720 kB (1 row) regress=# -- Total time 742ms,index size 3720kB regress=# -- Difference: about 44% time increase,about 68% index size increase. regress=# -- Big-ish,but whether you care depends on your application. Now: regress=# REINDEX INDEX composite_idx ; REINDEX Time: 342.283 ms regress=# SELECT pg_size_pretty(pg_indexes_size('demo'::regclass)); pg_size_pretty ---------------- 2208 kB (1 row) regress=# -- Index is back to same size,but total time for insert with progressive regress=# -- index build plus reindex at the end us up to 1084.283,twice as long as regress=# -- dropping the indexes,inserting the data,and re-creating the indexes took.
所以:
>对于OLAP,删除索引,插入,重新创建索引.
>对于OLTP,您可能只想坚持使用渐进式索引构建.考虑索引上的非100%fillfactor以降低插入成本.
>避免插入渐进式索引构建然后重新索引,这是两个世界中最糟糕的.
当然,此测试中使用的尺寸是玩具桌尺寸,因此您应该对现实世界数据和索引的样本重复此测试,以便深入了解它对您的影响程度.我以比上述更大的比例因子100重复这些测试,并且如果逐渐构建,则始终发现索引几乎是大小的两倍,尽管相对构建时间差异实际上在这个特定测试中下降.
所以:使用您的数据和架构进行测试.