Database

表的維護:截斷和重新填充後是否需要重新索引表?

  • April 24, 2013

我有一個表,其中包含大約 200 萬行我們用於分析的事務數據。每週我們都會用新數據重新載入它,所以我們一直在使用 TRUNCATE 來清除它,然後插入新行。

表上有幾個索引。如果我不刪除並重新創建索引,我是否需要在每次截斷和重新填充後重新索引,還是沒有必要?我應該在 TRUNCATE 之後執行 VACUUM,還是也沒有必要?

不,您通常不需要在之後重新索引TRUNCATE- 如果這樣做,您最好刪除索引,載入數據,然後在最後重新創建索引。

它有點類似於關於集群的這個答案- Pg 在插入數據期間自動刪除索引TRUNCATE,然後在插入數據時增量重建它,因此在TRUNCATE.

如果刪除索引、截斷、插入數據並重新創建索引,您可能會獲得更緊湊和更有效的索引。他們肯定會更快地建構。建構後的索引性能差異可能不足以保證大多數應用程序僅使用 b-tree 索引的額外工作,但填充表所需時間的差異可能非常值得。如果您使用 GiST 或(尤其是)GIN,最好刪除索引並在最後重新創建。

如果這樣做方便,請刪除索引並在最後添加它們,如果這對您不實用,請不要太擔心。

對於我測試中的正常 b 樹,增量創建的複合索引為 3720kb,而一次性創建的索引為 2208kb。建構時間為 164 毫秒(插入)+ 347 毫秒(索引)與 742 毫秒(插入+索引)。這種差異是顯著的,但不足以成為一個大問題,除非你正在做大規模的 DW。REINDEX在插入+索引執行後,A又花了 342 毫秒。看

因此,@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, sometext)
SELECT x, (x%100)::text
FROM generate_series(1,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% 的填充因子以降低插入成本。
  • 避免使用漸進式索引建構插入然後重新索引,這是兩全其美的。

當然,此測試中使用的尺寸是玩具桌尺寸,因此您應該對真實世界數據和索引的樣本重複此測試,以充分了解它對有多大的影響。我用比上述值大 100 的比例因子重複了這些測試,並且始終發現如果增量建構,索引幾乎正好是兩倍大小,儘管相對建構時間差異實際上在這個特定測試中下降了。

所以:用你的數據和模式進行測試。

引用自:https://serverfault.com/questions/501744