PostgreSQL修改列與重寫表

老版本的PostgreSQL在新增列時,會rewrite全表,至關於vacuum full table_name。這對生產是很是不利的,嚴重致使讀寫效率的低下。高版本已經有所改善,下面檢驗之。

檢查有沒有rewrite表,能夠查看它的系統列ctid的變化來驗證。

DB:PostgreSQL 9.1.2
postgres=# \d tab_kenyon                            
         Table "public.tab_kenyon"
 Column |         Type          | Modifiers 
--------+-----------------------+-----------
 id     | integer               | 
 name   | character varying(35) | 
 remark | text                  |
驗證過程以下:
postgres=# vacuum full tab_kenyon;
VACUUM
postgres=# select ctid,* from tab_kenyon ;
 ctid  | id |     name     | remark 
-------+----+--------------+--------
 (0,1) |  1 | kenyon       | 
 (0,2) |  2 | china        | 
 (0,3) |  5 | oopoo        | 
 (0,4) | 45 | xxooxx       | 
 (0,5) |  4 | i love china | 
(5 rows)

postgres=# update tab_kenyon set name = 'kenyon_test' where id = 5;
UPDATE 1
postgres=# select ctid,* from tab_kenyon ;                         
 ctid  | id |     name     | remark 
-------+----+--------------+--------
 (0,1) |  1 | kenyon       | 
 (0,2) |  2 | china        | 
 (0,4) | 45 | xxooxx       | 
 (0,5) |  4 | i love china | 
 (0,6) |  5 | kenyon_test  | 
(5 rows)
能夠看到ctid已經沒有了(0,3),而是新增了(0,6),這是新老版本混在一塊兒的緣故,老版本的數據不可見,並將被清理。
postgres=# alter table tab_kenyon add tt varchar(2);
ALTER TABLE
postgres=# select ctid,* from tab_kenyon ;          
 ctid  | id |     name     | remark | tt 
-------+----+--------------+--------+----
 (0,1) |  1 | kenyon       |        | 
 (0,2) |  2 | china        |        | 
 (0,4) | 45 | xxooxx       |        | 
 (0,5) |  4 | i love china |        | 
 (0,6) |  5 | kenyon_test  |        | 
(5 rows)
能夠看到ctid並無更改,也就是說沒有重寫表(rewrite table)。

換一個場景,新增帶default值的列
postgres=# alter table tab_kenyon add yy varchar(2) default 'Y';
ALTER TABLE
postgres=# select ctid,* from tab_kenyon ;                      
 ctid  | id |     name     | remark | tt | yy 
-------+----+--------------+--------+----+----
 (0,1) |  1 | kenyon       |        |    | Y
 (0,2) |  2 | china        |        |    | Y
 (0,3) | 45 | xxooxx       |        |    | Y
 (0,4) |  4 | i love china |        |    | Y
 (0,5) |  5 | kenyon_test  |        |    | Y
(5 rows)
此時能夠看到ctid的值有了變化了。

總結:
1.新增NULL列時只是更新字典信息表,而不會對基礎表重寫,系統只會保持很是短期的鎖
2.新增非NULL列時會更新基礎表
3.修改表結構時是會阻塞表的讀寫的,能夠用begin...end來模擬
4.PG的9.2版本更加減小了alter table的表重寫,以下是場景
varchar(x) --> varchar(y) 當 y>=x. 或varchar(x) --> varchar or text (no size limitation)
numeric(x,z) --> numeric(y,z) 當 y>=x, or to numeric without specifier
varbit(x) --> varbit(y) when y>=x, or to varbit without specifier
timestamp(x) --> timestamp(y) when y>=x or timestamp without specifier
timestamptz(x) --> timestamptz(y) when y>=x or timestamptz without specifier
interval(x) --> interval(y) when y>=x or interval without specifier

參考: http://wiki.postgresql.org/wiki/What's_new_in_PostgreSQL_9.2
相關文章
相關標籤/搜索