Oracle轉換user_tab_columns中high_value值為十進位制
今天本想計算下基於範圍的索引選擇率,但是通過user_tab_columns查詢出來low_value和high_value結果是raw型別的,而且我們知道它是擷取了後32位,
如果我想知道他們代表確切的十進位制數將是什麼呢?折騰了半天從網上查到計算方法(以前用過忘了),記錄下備用:
從user_tab_columns查出的結果:
SQL> select table_name,column_name,low_value,high_value from user_tab_columns where table_name='T1' and column_name='CLUSTERED';
TABLE COLUMN_NAM LOW_VALUE HIGH_VALUE
----- ---------- ---------- ----------
T1 CLUSTERED 80 C164
實際最大最小值是這樣的:
SQL> select min(CLUSTERED) min_value,max(CLUSTERED) max_value from t1;
MIN_VALUE MAX_VALUE
---------- ----------
0 99
用utl_raw包的cast_to_number函式進行型別轉換如下:
SQL> select table_name,
2 column_name,
3 utl_raw.cast_to_number(low_value) low,
4 utl_raw.cast_to_number(high_value) hight
5 from user_tab_col_statistics
6 where table_name = 'T1'
7 and column_name = 'CLUSTERED';
TABLE COLUMN_NAM LOW HIGHT
----- ---------- ---------- ----------
T1 CLUSTERED 0 99
ok,和表中時間最小最大值一致。
low_value和high_value對優化器選擇執行計劃有什麼影響?下面這個測試有點白痴,統計資訊沒有變,Oracle很自然地選擇了和之前一樣的執行計劃嘍。
測試資料:
create table t(id,name)
as select rownum rn,'A' from dual connect by level<=10000;
create index idx_t_id on t(ID);
analyze table t compute statistics for table for all indexes for all indexed columns;
SQL> select table_name,column_name,high_value,low_value from user_tab_columns where table_name='T' and column_name='ID';
TABLE COLUMN_NAM HIGH_VALUE LOW_VALUE
----- ---------- ---------- ----------
T ID C302 C102
插一句:是不是好奇high_value和low_value怎麼算的?
SQL> select upper(replace(substr(dump(min(id), 16, 0, 32),
2 instr(dump(min(id), 16, 0, 32), ':', 1) + 1),',','0')) low_value,
3 upper(replace(substr(dump(max(id), 16, 0, 32),
4 instr(dump(max(id), 16, 0, 32), ':', 1) + 1),',','0')) high_value
5 from t;
LOW_VALUE HIGH_VALUE
---------- ----------
C102 C302
即在原先最小值基礎上取dump,轉換為16進位制,然後取前32位資料。將取得資料逗號替換為0即可。
SQL> select table_name,
2 column_name,
3 utl_raw.cast_to_number(low_value) low,
4 utl_raw.cast_to_number(high_value) hight
5 from user_tab_col_statistics
6 where table_name = 'T' and column_name='ID';
TABLE COLUMN_NAM LOW HIGHT
----- ---------- ---------- ----------
T ID 1 10000
當id<100時走的是索引範圍掃描:
SQL> select * from t where id<100;
已選擇99行。
執行計劃
----------------------------------------------------------
Plan hash value: 514881935
------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost |
------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 99 | 594 | 3 |
| 1 | TABLE ACCESS BY INDEX ROWID| T | 99 | 594 | 3 |
|* 2 | INDEX RANGE SCAN | IDX_T_ID | 99 | | 2 |
------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("ID"<100)
SQL> delete from t where id>=101;
已刪除9900行。
SQL> commit;
提交完成。
如下查詢說證明明統計資訊沒有變:
SQL> select table_name,
2 column_name,
3 utl_raw.cast_to_number(low_value) low,
4 utl_raw.cast_to_number(high_value) hight
5 from user_tab_col_statistics
6 where table_name = 'T' and column_name='ID';
TABLE COLUMN_NAM LOW HIGHT
----- ---------- ---------- ----------
T ID 1 10000
SQL> select * from t where id<100;
已選擇99行。
執行計劃
----------------------------------------------------------
Plan hash value: 514881935
------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost |
------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 99 | 594 | 3 |
| 1 | TABLE ACCESS BY INDEX ROWID| T | 99 | 594 | 3 |
|* 2 | INDEX RANGE SCAN | IDX_T_ID | 99 | | 2 |
------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("ID"<100)
可以看到海是走了索引範圍掃描,而此時表裡只剩下100個資料而已。
重新收集下統計資訊看看:
SQL> analyze table t compute statistics for table for all indexes for all indexed columns;
表已分析。
SQL> select table_name,
2 column_name,
3 utl_raw.cast_to_number(low_value) low,
4 utl_raw.cast_to_number(high_value) hight
5 from user_tab_col_statistics
6 where table_name = 'T' and column_name='ID';
TABLE COLUMN_NAM LOW HIGHT
----- ---------- ---------- ----------
T ID 1 100
ok統計資訊已經變了。
SQL> select * from t where id<100;
已選擇99行。
執行計劃
----------------------------------------------------------
Plan hash value: 1601196873
----------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost |
----------------------------------------------------------
| 0 | SELECT STATEMENT | | 100 | 500 | 4 |
|* 1 | TABLE ACCESS FULL| T | 100 | 500 | 4 |
----------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("ID"<100)
執行計劃變了。
也就是說high_value和low_value反應了該列的最大最小值。此例說明,如果資料改變了而不及時收集統計資訊,很可能會造成優化器選擇錯誤的執行計劃。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/24496749/viewspace-734991/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 十六進位制轉換為十進位制
- Oracle中十進位制與十六進位制轉換程式Oracle
- JavaScript十進位制轉換為二進位制JavaScript
- Oracle二進位制與十進位制轉換Oracle
- 【轉帖】Oracle中的二進位制、八進位制、十進位制、十六進位制相互轉換函式Oracle函式
- Oracle中的二進位制、八進位制、十進位制、十六進位制相互轉換函式Oracle函式
- JavaScript 二進位制數字轉換為十進位制JavaScript
- Qt進位制轉換(十進位制轉十六進位制)QT
- 【進位制轉換】十進位制與十六進位制相互轉換方法
- 二進位制轉十進位制快速轉換方法
- Oracle中的進位制轉換Oracle
- Python 十進位制轉換為二進位制 高位補零Python
- ORACLE使用函式對二進位制、十進位制、十六進位制數互相轉換Oracle函式
- oracle 給的轉換函式實現 十六進位制---->十進位制Oracle函式
- 十進位制轉換為十六進位制和二進位制程式碼例項
- 二進位制,八進位制,十進位制,十六進位制的相互轉換
- 十進位制與二進位制互相轉換指南
- oracle中進位制轉換函式Oracle函式
- 進位制之間的轉換之“十六進位制 轉 十進位制 轉 二進位制 方案”
- 十六進位制轉換為八進位制
- java中二進位制、八進位制、十進位制、十六進位制的轉換Java
- 二進位制,八進位制,十進位制,十六進位制之間的轉換
- Python 進位制互相轉換(二進位制、十進位制和十六進位制)Python
- 十進位制轉換任意進位制--鏈棧實現
- js二進位制和十進位制轉換程式碼JS
- jQuery顏色值轉換為十六進位制形式jQuery
- 【進位制轉換】二進位制、十六進位制、十進位制、八進位制對應關係
- JAVA 二進位制,八進位制,十六進位制,十進位制間進行相互轉換Java
- (轉)【iOS 開發】二進位制、十進位制、十六進位制相互轉換的方法iOS
- 遞迴函式實現十進位制正整數轉換為二進位制,八進位制,十六進位制遞迴函式
- ORACLE中用一條SQL實現其它進位制到十進位制的轉換OracleSQL
- lua之m進位制轉換為n進位制-任意進位制轉換演算法演算法
- 計算機基礎進位制轉換(二進位制、八進位制、十進位制、十六進位制)計算機
- 1474 十進位制轉m進位制+1475 m進位制轉十進位制
- 大話二進位制,八進位制,十進位制,十六進位制之間的轉換
- javascript十進位制數字和二進位制相互轉換JavaScript
- shell 中轉換16進位制10進位制
- n進位制轉十進位制