Oracle11g新特性 - 快速線上新增not null欄位
問題:某電信系統業務,其中有一張表有上億條資訊記錄,而且很重要;要求在不停庫和不鎖表的情況下;對該表增加一個新的欄位,如何實現。
在以前,在表中新增一個NOT NULL欄位是件十分痛苦的事情,尤其是在表很大的情況,不但執行速度慢(會產生DDL鎖,影響其它使用者操作),而且由於資料長度的增加,很容易造成表中大量的行連結情況,影響效能。
在11g中,這種情況得到了徹底的改善,Oracle透過在資料字典(ecol$)中記錄DEFAULT值,避免了繁重的更新操作,增加非空欄位的時間和增加一個可空欄位的時間完全一樣。
下面先看中的情況:
SQL> select * from v$version where rownum<2;
BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - Prod
SQL> create test as select * from dba_objects;
Table created.
SQL> select count(*) from test;
COUNT(*)
----------
24871
SQL> set timing on
SQL> alter table test add new_col varchar(1000)default'LARGE COLUMN'not null;
Table altered.
Elapsed: 00:00:20.34
可以看到即使對於只有2萬多條資料的表,用了20秒,而且在這20秒期間,該表上有DDL鎖,所有在該表的DML操作都會被阻塞。
注意,這裡新增的列是非空的,如果沒有非空這個限制,在10g中也是很快的:
SQL> alter table test add new_col2 varchar(1000);
Table altered.
Elapsed: 00:00:00.59
下面再看11g中的情況:
SQL> select * from v$version where rownum<2;
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production
SQL> create table test as select * from dba_objects;
Table created.
SQL> select count(*) from dba_objects;
COUNT(*)
----------
13617
SQL> set timing on
SQL> alter table test add new_col varchar(1000) default 'LARGE COLUMN' not null;
Table altered.
Elapsed: 00:00:01.34
可以看到在11g中只用了1秒,那麼Oracle是採用何種方法實現瞭如此大的效能提升呢?說起來也簡單,在Oracle11g中,當新增一個包含DEFAULT值的NOT NULL欄位,Oracle不會去更新現有的資料,僅僅是將預設值以及對應的表資訊、列資訊一起儲存在一個新增資料字典表ecol$中。當Oracle在讀取資料時,如果發現某一列為非空,但是實際儲存卻為空,就會從ECOL$中讀取該列的預設值。
這樣做的好處是不但減少了執行時間,而且不會產生DDL鎖,進而不會影響其它使用者的操作。
============
回到最開始的問題,如果版本不是11g,那該怎麼辦呢,其實可以先新建一個允許空的欄位,然後把該欄位修改會非空,在對之前的資料進行update操作:
1. 新建一個允許空的欄位。
SQL> alter table test add new_col varchar(1000);
Table altered.
Elapsed: 00:00:00.14
2. 修改該欄位為非空,該語句只對之後的記錄起作用,原有記錄的該列還是為空值,因此該操作也很快。
SQL> alter table test modify new_col varchar(1000) default 'LARGE COLUMN';
Table altered.
Elapsed: 00:00:00.48
3. 更新原有的欄位為預設值。
SQL> alter session enable parallel dml;
SQL> update /*+ parallel(t 8) */ test set new_col='LARGE COLUMN' where new_col is null;
24871 rows updated.
SQL> alter session disable parallel dml
在以前,在表中新增一個NOT NULL欄位是件十分痛苦的事情,尤其是在表很大的情況,不但執行速度慢(會產生DDL鎖,影響其它使用者操作),而且由於資料長度的增加,很容易造成表中大量的行連結情況,影響效能。
在11g中,這種情況得到了徹底的改善,Oracle透過在資料字典(ecol$)中記錄DEFAULT值,避免了繁重的更新操作,增加非空欄位的時間和增加一個可空欄位的時間完全一樣。
下面先看中的情況:
SQL> select * from v$version where rownum<2;
BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - Prod
SQL> create test as select * from dba_objects;
Table created.
SQL> select count(*) from test;
COUNT(*)
----------
24871
SQL> set timing on
SQL> alter table test add new_col varchar(1000)default'LARGE COLUMN'not null;
Table altered.
Elapsed: 00:00:20.34
可以看到即使對於只有2萬多條資料的表,用了20秒,而且在這20秒期間,該表上有DDL鎖,所有在該表的DML操作都會被阻塞。
注意,這裡新增的列是非空的,如果沒有非空這個限制,在10g中也是很快的:
SQL> alter table test add new_col2 varchar(1000);
Table altered.
Elapsed: 00:00:00.59
下面再看11g中的情況:
SQL> select * from v$version where rownum<2;
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production
SQL> create table test as select * from dba_objects;
Table created.
SQL> select count(*) from dba_objects;
COUNT(*)
----------
13617
SQL> set timing on
SQL> alter table test add new_col varchar(1000) default 'LARGE COLUMN' not null;
Table altered.
Elapsed: 00:00:01.34
可以看到在11g中只用了1秒,那麼Oracle是採用何種方法實現瞭如此大的效能提升呢?說起來也簡單,在Oracle11g中,當新增一個包含DEFAULT值的NOT NULL欄位,Oracle不會去更新現有的資料,僅僅是將預設值以及對應的表資訊、列資訊一起儲存在一個新增資料字典表ecol$中。當Oracle在讀取資料時,如果發現某一列為非空,但是實際儲存卻為空,就會從ECOL$中讀取該列的預設值。
這樣做的好處是不但減少了執行時間,而且不會產生DDL鎖,進而不會影響其它使用者的操作。
============
回到最開始的問題,如果版本不是11g,那該怎麼辦呢,其實可以先新建一個允許空的欄位,然後把該欄位修改會非空,在對之前的資料進行update操作:
1. 新建一個允許空的欄位。
SQL> alter table test add new_col varchar(1000);
Table altered.
Elapsed: 00:00:00.14
2. 修改該欄位為非空,該語句只對之後的記錄起作用,原有記錄的該列還是為空值,因此該操作也很快。
SQL> alter table test modify new_col varchar(1000) default 'LARGE COLUMN';
Table altered.
Elapsed: 00:00:00.48
3. 更新原有的欄位為預設值。
SQL> alter session enable parallel dml;
SQL> update /*+ parallel(t 8) */ test set new_col='LARGE COLUMN' where new_col is null;
24871 rows updated.
SQL> alter session disable parallel dml
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/196700/viewspace-714275/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- MySQL線上新增欄位的幾種方案介紹MySql
- 快速將下劃線欄位改為駝峰欄位
- json轉化保留null欄位JSONNull
- fastadmin 新增欄位記圖片欄位AST
- Mybatis-Plus 更新欄位為 NULLMyBatisNull
- Oracle12C新特性_不可見欄位(二)Oracle
- MySQL-去掉不為null的欄位MySqlNull
- PG11新特性解讀:新增非空預設值欄位不需要重寫表
- Oracle-欄位的新增Oracle
- sql 統計多個欄位的和(如果欄位中含有 null 的處理)SQLNull
- MySQL null值欄位是否使用索引的總結MySqlNull索引
- 為什麼資料庫欄位要使用NOT NULL?資料庫Null
- MySQL欄位新增註釋,但不改變欄位的型別MySql型別
- 如何給 PHP 新增新特性PHP
- MySQL欄位究竟是否需要設定成not nullMySqlNull
- mysql資料庫新增和修改欄位MySql資料庫
- laravel生產環境下新增欄位Laravel
- 每次上線都要加欄位,走變更,如何破局?
- 面試題:對NotNull欄位插入Null值 有啥現象?面試題Null
- laravel-query-builder 對於欄位 值為 null的排序方式LaravelUINull排序
- jpa~為欄位新增insert的預設值
- 12c新特性,線上move資料檔案
- 如何給SAP Cloud for Customer UI上的欄位新增自定義校驗邏輯CloudUI
- MybatisPlus經典示例:使用Wrapper查詢指定欄位並新增欄位函式處理MyBatisAPP函式
- 欄位管理,為什麼只有新增的時候才自動匹配欄位型別型別
- [20201224]order by欄位順序與查詢條件為NULL.txtNull
- java查詢資料庫,int型欄位為null的情況Java資料庫Null
- 無法在SAP Fiori UI上新增擴充套件欄位?原因可能就在這裡UI套件
- 億級大表線上不鎖表變更欄位與索引索引
- MySQL 5.7新特性之線上收縮undo表空間MySql
- Oracle 增加修改刪除欄位與新增註釋Oracle
- 新增一列並增加列欄位註釋
- 如果新增欄位是外來鍵,如何處理?
- Oracle-新增一個欄位並設定日期Oracle
- oracle11g RAC新增節點Oracle
- Spring Boot 2.0 新特性(二):新增事件ApplicationStartedEventSpring Boot事件APPdev
- [提問交流]建立模型,新增屬性,欄位型別如何設定2位小數的欄位型別模型型別
- PostgreSQL技術週刊第9期:PostgreSQL11新特性解讀之新增非空預設值欄位不需要重寫表SQL
- 技術乾貨| MongoDB如何查詢Null或不存在的欄位?MongoDBNull