表的維護:截斷和重新填充後是否需要重新索引表?
我有一個表,其中包含大約 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 的比例因子重複了這些測試,並且始終發現如果增量建構,索引幾乎正好是兩倍大小,儘管相對建構時間差異實際上在這個特定測試中下降了。
所以:用你的數據和模式進行測試。