oracle 11g 虛擬列
11g虛擬列
virtual column不儲存資料,執行時候根據一個基於其它欄位的表示式生成該列的內容(重點在於不儲存資料),應用長期使用表示式比較有用,只對cbo有效.
簡單使用
SQL> create table t_extent (a int,b as(1+a));
Table created.
SQL> insert into t_extent(a) values(1);
1 row created.
SQL> commit;
Commit complete.
SQL> select * from t_extent;
A B
---------- ----------
1 2
alter table add column
SQL> create table t1(a int);
Table created.
SQL> insert into t1 values(1);
1 row created.
SQL> commit;
SQL> alter table t1 add b as (a+1);
Table altered.
SQL> SQL> select * from t1;
A B
---------- ----------
1 2
統計資訊與虛擬列
create table t1
nologging
as
select
decode( mod(rownum,4),
0, 'England',
1, 'Northern Ireland',
2, 'Scotland',
3, 'Wales',
'Great Britain'
) country,
decode( mod(rownum,2),
0,'Australia',
1,'America',
'Other'
) continent,
'Earth' planet,
1 one
from
all_objects
where
rownum <= 3000
;
SQL> execute dbms_stats.gather_table_stats('SYS','T1');
PL/SQL procedure successfully completed.
SQL> select table_name,column_name,density,num_nulls,num_distinct from user_tab_col_statistics where table_name='T1';
TABLE_NAME COLUMN_NAME DENSITY NUM_NULLS NUM_DISTINCT
------------------------------ ------------------------------ ---------- ---------- ------------
T1 COUNTRY .25 0 4
T1 CONTINENT .5 0 2
T1 PLANET 1 0 1
T1 ONE 1 0 1
SQL> select count(*) from t1 where COUNTRY='Wales';
COUNT(*)
----------
750
SQL> set autotrace trace exp
SQL> select * from t1 where COUNTRY='Wales';
Execution Plan
----------------------------------------------------------
Plan hash value: 3617692013
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 750 | 21000 | 6 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| T1 | 750 | 21000 | 6 (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("COUNTRY"='Wales')
SQL> select count(*) from t1 where upper(COUNTRY)='WALES';
Execution Plan
----------------------------------------------------------
Plan hash value: 3724264953
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 10 | 6 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 10 | | |
|* 2 | TABLE ACCESS FULL| T1 | 30 | 300 | 6 (0)| 00:00:01 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter(UPPER("COUNTRY")='WALES')
建立虛擬列
SQL> alter table t1 add up_COUNTRY as (upper(COUNTRY));
Table altered.
收集統計資訊
SQL> execute dbms_stats.gather_table_stats('SYS','T1');
PL/SQL procedure successfully completed.
SQL> select count(*) from t1 where upper(COUNTRY)='WALES';
Execution Plan
----------------------------------------------------------
Plan hash value: 3724264953
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 20 | 6 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 20 | | |
|* 2 | TABLE ACCESS FULL| T1 | 750 | 15000 | 6 (0)| 00:00:01 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("T1"."UP_COUNTRY"='WALES')
可以看到 虛擬列上收集 統計資訊後正確,另外 為此 oracle還加入了擴充套件統計資訊收集
類似使用 SQL> select dbms_stats.create_extended_stats(ownname=>'XH',tabname=>'T2',extension=>'(upper(a))') from dual;
具體擴充套件統計資訊 (具體 測試記錄 http://space.itpub.net/12020513/viewspace-624110)
虛擬列能解決的問題,可以代替函式index,建議 虛擬列 然後在上面建index,比如upper(name)這個可以建成一個虛擬列 並在上面建立index,而不用建立一個函式index
SQL> create table t2 (a int,b varchar2(10));
Table created.
declare
begin
for i in 1..5000 loop
insert into t2 values(i,'a'||i);
end loop;
commit;
end;
PL/SQL procedure successfully completed.
SQL> insert into t2 values(6000,'xhb');
1 row created.
SQL> insert into t2 values(6000,'axh');
1 row created.
SQL> commit;
Commit complete.
SQL> create index t2_id on t2(b);
Index created.
SQL> execute dbms_stats.gather_table_stats('SYS','T2');
PL/SQL procedure successfully completed.
SQL> SQL> select * from t2 where b like '%xh%';
A B
---------- ----------
6000 xhb
6000 axh
SQL> select CLUSTERING_FACTOR from user_indexes where index_name='T2_ID';
CLUSTERING_FACTOR
-----------------
904
like 開頭為% 或_,不會使用index,使用了fts,解決這種問題 通常是建立一個 reverse(X) 的函式index,查詢時候 使用reverse(XX) like reverse('%a') 可以走這個函式index
,現在有了虛擬列 我們可以建立一個 虛擬列,並在上面建立一個普通 index既可
SQL> select * from t2 where b like 'xh%';
Execution Plan
----------------------------------------------------------
Plan hash value: 3119810522
--------------------------------------------------------------------------------
-----
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time
|
--------------------------------------------------------------------------------
-----
| 0 | SELECT STATEMENT | | 1 | 9 | 3 (0)| 00:00
:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| T2 | 1 | 9 | 3 (0)| 00:00
:01 |
|* 2 | INDEX RANGE SCAN | T2_ID | 1 | | 2 (0)| 00:00
:01 |
--------------------------------------------------------------------------------
-----
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("B" LIKE 'xh%')
filter("B" LIKE 'xh%'
SQL> select * from t2 where b like '%xh';
Execution Plan
----------------------------------------------------------
Plan hash value: 1513984157
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 250 | 2250 | 5 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| T2 | 250 | 2250 | 5 (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("B" LIKE '%xh')
SQL> create index t2_id_re on t2(reverse(b));
Index created.
SQL> select CLUSTERING_FACTOR from user_indexes where index_name='T2_ID_RE';
CLUSTERING_FACTOR
-----------------
4982
SQL> Select * from t2 where reverse(b) like reverse('%xh');
A B
---------- ----------
6000 axh
SQL> select * from t2 where reverse(b) like reverse('%xh');
Execution Plan
----------------------------------------------------------
Plan hash value: 3865927368
--------------------------------------------------------------------------------
--------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Ti
me |
--------------------------------------------------------------------------------
--------
| 0 | SELECT STATEMENT | | 250 | 2250 | 4 (0)| 00
:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| T2 | 250 | 2250 | 4 (0)| 00
:00:01 |
|* 2 | INDEX RANGE SCAN | T2_ID_RE | 45 | | 2 (0)| 00
:00:01 |
--------------------------------------------------------------------------------
--------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access(REVERSE("B") LIKE 'hx%')
filter(REVERSE("B") LIKE 'hx%')
SQL> alter table t2 add d as (reverse(b));
Table altered.
SQL> create index t2_like_re on t2(d);
Index created.
SQL> execute dbms_stats.gather_table_stats('SYS','T2');
PL/SQL procedure successfully completed.
SQL> select CLUSTERING_FACTOR from user_indexes where index_name='T2_LIKE_RE';
CLUSTERING_FACTOR
-----------------
4982
SQL> select * from t2 where d like reverse('%xh');
A B D
---------- ---------- ----------
6000 axh hxa
SQL> select * from t2 where d like reverse('%xh');
Execution Plan
----------------------------------------------------------
Plan hash value: 194083129
--------------------------------------------------------------------------------
----------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
Time |
--------------------------------------------------------------------------------
----------
| 0 | SELECT STATEMENT | | 1 | 15 | 3 (0)|
00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| T2 | 1 | 15 | 3 (0)|
00:00:01 |
|* 2 | INDEX RANGE SCAN | T2_LIKE_RE | 1 | | 2 (0)|
00:00:01 |
--------------------------------------------------------------------------------
----------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("D" LIKE 'hx%')
filter("D" LIKE 'hx%')
分割槽表 針對FTS 的優化基本就是優化logical reads,那麼分割槽表的分割槽修剪是極其有必要的,當<>,not in ,not null,表示式,函式 時候將不會使用分割槽修剪
那麼針對,函式,表示式的情況 可以用 虛擬列 解決(必須要使用 虛擬列作為分割槽KEY,分割槽修剪必須要where條件中有分割槽key)
create table t3 (id number,name varchar2(50))
partition by range(id)(
partition t3_range_p1 values less than (1000),
partition t3_range_p2 values less than (2000),
partition t3_range_p3 values less than (3000) ,
partition t3_range_pmax values less than (maxvalue));
Table created.
declare
begin
for i in 1..5000 loop
insert into t3 values(i,'a'||i);
end loop;
commit;
end;
/
execute dbms_stats.gather_table_stats('SYS','T3')
SQL> set linesize 1000
SQL> select * from t3 where id=100;
Execution Plan
----------------------------------------------------------
Plan hash value: 2814083523
-----------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
-----------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 8 | 2 (0)| 00:00:01 | | |
| 1 | PARTITION RANGE SINGLE| | 1 | 8 | 2 (0)| 00:00:01 | 1 | 1 |
|* 2 | TABLE ACCESS FULL | T3 | 1 | 8 | 2 (0)| 00:00:01 | 1 | 1 |
-----------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("ID"=100)
SQL> select * from t3 where to_char(id)='100';
Execution Plan
----------------------------------------------------------
Plan hash value: 947723311
--------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
--------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 9 | 5 (0)| 00:00:01 | | |
| 1 | PARTITION RANGE ALL| | 1 | 9 | 5 (0)| 00:00:01 | 1 | 4 |
|* 2 | TABLE ACCESS FULL | T3 | 1 | 9 | 5 (0)| 00:00:01 | 1 | 4 |
--------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter(TO_CHAR("ID")='100')
可以看到 掃描了 4個分割槽
create table t4 (id number,name varchar2(50),char_id as (to_char(id)))
partition by range(char_id)(
partition t4_range_p1 values less than (1000),
partition t4_range_p2 values less than (2000),
partition t4_range_p3 values less than (3000) ,
partition t4_range_pmax values less than (maxvalue));
declare
begin
for i in 1..5000 loop
insert into t4(id,name) values(i,'a'||i);
end loop;
commit;
end;
SQL> execute dbms_stats.gather_table_stats('SYS','T4')
PL/SQL procedure successfully completed.
SQL> select * from t4 where char_id='100';
Execution Plan
----------------------------------------------------------
Plan hash value: 3296030324
-----------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
-----------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 10 | 2 (0)| 00:00:01 | | |
| 1 | PARTITION RANGE SINGLE| | 1 | 10 | 2 (0)| 00:00:01 | 1 | 1 |
|* 2 | TABLE ACCESS FULL | T4 | 1 | 10 | 2 (0)| 00:00:01 | 1 | 1 |
-----------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("CHAR_ID"='100')
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/12020513/viewspace-631364/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 【VIRTUAL COLUMN】Oracle 11g中的虛擬列技術Oracle
- Oracle11新特性——虛擬列Oracle
- Oracle 11g RMAN虛擬私有目錄Oracle
- Oracle中的虛擬列索引-nosegment indexOracle索引Index
- Oracle11新特性——虛擬列(二)Oracle
- 11g新特性--基於虛擬列的分割槽
- MySQL虛擬列MySql
- oracle 11G RAC的建立(VM虛擬環境)Oracle
- oracle11g新特性之--虛擬列Oracle
- Oracle11G 虛擬列 Virtual Column使用Oracle
- Oracle虛擬索引Oracle索引
- mysql 5.7 虛擬列功能MySql
- 虛擬歌姬列傳
- Oracle之虛擬索引Oracle索引
- 連線虛擬機器oracle 和虛擬機器KEY虛擬機Oracle
- 利用虛擬列實現虛擬刪除的主外來鍵約束
- 藉助 VMware 虛擬化 OracleOracle
- oracle 11g的行轉列、列轉行Oracle
- jvm HotSpot虛擬機器主要參數列JVMHotSpot虛擬機
- oracle 根據虛擬列建立以周幾為單位的分割槽表Oracle
- Oracle效能優化之虛擬索引Oracle優化索引
- ORACLE DISCOVERER虛擬記憶體低Oracle記憶體
- 一次Linux虛擬機器安裝Oracle 11G資料庫經歷Linux虛擬機Oracle資料庫
- VirtualBox透過命令列操作虛擬機器命令列虛擬機
- MySQL5.7 虛擬列實現表示式索引MySql索引
- VM虛擬機器下在LINUX上安裝ORACLE 11G單例項資料庫虛擬機LinuxOracle單例資料庫
- Oracle效能最佳化之虛擬索引Oracle索引
- oracle 虛擬專用資料庫(VPD)Oracle資料庫
- 介紹Oracle Virtual Index虛擬索引(上)OracleIndex索引
- Oracle VM:虛擬環境下的Oracle VC認證Oracle
- 虛擬函式,虛擬函式表函式
- 虛擬函式 純虛擬函式函式
- openNebula 運維繫列虛擬機器virtual machines operations運維虛擬機Mac
- 虛擬機器 Centos5.5 安裝oracle虛擬機CentOSOracle
- Oracle安全 - 虛擬專用資料庫 VPDOracle資料庫
- Dalvik虛擬機器、Java虛擬機器與ART虛擬機器虛擬機Java
- 虛擬化四、KVM虛擬化技術
- 虛擬機器arm虛擬環境搭建虛擬機