Oracle reverse函數

Oracle reverse函數
2007-10-25 14:06
reverse函數功能就是反向排列給定的數組元素

SQL> create or replace function Re(s string) return varchar2 is
Result varchar2(1000);
v_s string(1000);
begin
for i in 1..length(s)
loop
Result:=Result||substr(s,length(s)-i+1,1);
end loop;
return(Result);
end Re;

1.3.3 索引
Oracle 9i中有6種可以使用的索引:B-Tree索引(不指定任何選項的創建方法所創建)、壓縮B樹索引、Bitmap(位圖)索引、基於函數的索引、 Reverse Key Index(RKI,反向鍵索引)、Index Organized Table(IOT,索引組織表)。

1.3.3.1 檢查索引信息
 dba_indexes
index_type (normal-B樹,normal/rev-反向鍵,function-based normal,bitmap,iot-top,cluster,lob)
compression
funcidx_status

 dba_segments
segment_name
segment_type
tablespace_name

 dba_tables
SQL> select table_name,iot_name,iot_type,tablespace_name from dba_tables where iot_type is not null;
就可以觀察出IOT益出的情況。 Tablespace_name 爲空,說明爲一個索引而不是一個表。

 監視索引使用情況
如果一個索引永遠得不到,應該刪除:
1)消除了對被索引表DML操作時的索引維護系統開銷。
2)釋放表空間。

執行SQL>alter index c_unicom.idx_ne_cell monitoring usage;
一段時間後執行SQL> alter index unicom.idx_ne_cell nomonitoring usage;
此時查詢v$object_usage(Oracle 9i)的used列,YES表示監視期間至少得到過一次訪問。NO表示未得到訪問。


1.3.3.2 B-Tree索引
 基礎概念
也叫平衡樹索引。
是按升序對被索引的列進行排序,同時存儲一個行ID,用來指出該行的其他數據的物理存儲地,Oracle以一種樹型結構來存儲這些數。
查詢時,首先搜索該多級樹結構形式組織的索引,然後按ID訪問需要的表數據。
1)如果表數據行很多,只返回一個表中的少數行(Oracle建議是5%)。
2)具有高基數的列。且這些列經常被用在where條件中。
此時Oracle建議創建一個B樹索引。
如:Create index idx_ne_cell on ne_cell(ne_id) tablespace unicom_dbs;

 判斷是否需要重建索引
B樹索引設計爲總是平衡的,Oracle隨着insert操作而連續的分裂索引塊,但是,隨着insert和delete操作,該索引會產生許多級,增加索引從根遍歷的時間,降低了效率,此時需要重建索引。
Oracle建議:
1)當級別深度到4或超過4時。(增加了從根遍歷的時間)
索引被分析後,執行select index_name,blevel from dba_indexes where blevel >=4;檢查
2)被刪除數佔總數的20%以上時。(增加了訪問某項所訪問的index塊數)
- 執行analyze index idx_ne_cell validate structure;填充表index_stats數據。
- 執行select (del_lf_rows_len/lf_rows_len)*100 “Wasted Space”
from index_stats where name=’IDX_NE_CELL’;

Column Description
LF_ROWS Number of values currently in the index
LF_ROWS_LEN Sum in bytes of the length of all values
DEL_LF_ROWS Number of values deleted from the index
DEL_LF_ROWS_LEN Length of all deleted values

 重建索引
在一個不穩定的表上建索引會影響性能,一個索引block只有完全空時才能進入free list,即使一個索引block裏只含有一個條目,它也必須被維護,因此索引需要進行階段性的重建。
- 刪除該index並執行create index ...開始創建。
是最耗時的方法,也是資源密集型。但7.3前版本只能這麼做。
- alter index .. rebuild tablespace ..;
使用現有索引項來重建索引,很快。同時能把索引轉移到其他表空間。但創建的過程中,新舊索引同時存在,要求有額外的臨時空間可用。
SQL>alter index idx_ne_cell rebuild online;
使用online來儘可能減少創建過程中出現的任何加鎖問題。
- alter index .. coalesce;
只是將處於同一個索引分支內的葉塊拼合起來,很快,不要求額外的磁盤空間,最大限度的減少了創建過程中出現的任何加鎖問題。但此方法不能轉移索引到另外一個表空間。

更多關於alter index 參考 9.0.1 A901177-01的16章。

1.3.3.3 壓縮B樹索引
如果B樹索引非常大,此時就建議使用壓縮B樹索引了。
壓縮B樹索引:在索引列存在重複值時,只記錄一個值和不同的row id,減少了重複的列值的存儲(同理,基數非常大或列值都唯一的,壓縮就沒多少必要了)。最大限度的減少了B樹索引佔用的磁盤空間。同時索引掃描也會訪問更少的數據庫塊,減少I/O。

壓縮語句:
SQL>create index idx_alarminfo on alarminfo(ALARMOBJECT) tablespace unicom_dbs compress;
或:
SQL>alter index idx_alarminfo rebuild compress;

1.3.3.4 Bitmap(位圖)索引
創建錶行的一個二進制映像,比如是存儲1,不是存儲0。所以佔用更少的存儲空間。
1)位圖索引檢索、匹配的行會更快。
2)對於底基數列,工作的更好。(高基數,B樹好)
3)被索引表要DML操作少、長度大、有極少不同值的表列上極有用。(DML操作會引起位圖級的加鎖發生,而且要求重建所有可能值的整個位圖;即使發生很多行被操作,但只按一次DML進行更新)
4)適合在決策支持系統或數據倉庫使用。

SQL>create bitmap index idx_ne_cell on ne_cell(related_bsc);
//加大sort_area_size和pga_aggregate_target通常會加快bitmap index的創建和操作。

1.3.3.5 基於函數的索引
函數索引適用於B樹索引和bitmap索引。但必須把init.ora的query_rewrite_enabled參數設置成true纔可使用。(默認是false)
在SQL語句的WHERE字句中有任一函數或操作被運用於一個索引列時,執行計劃將使用全表掃描而不會使用非函數索引。
如:select last_name,first_name from employee
where upper(first_name) = ‘REGINALD’;
或:select product_id,units,price,price*units from sales
where (price*units) > 10000;
都不會使用first_name或price或units列上的索引。

如下創建函數索引後優化程序纔會考慮使用索引:
SQL>create index idx_first_name_employee on employee (upper(first_name));
SQL>create index idx_sales_total on sales (price*units) tablespace ind_dbs;

1.3.3.6 Reverse Key Index
屬於B樹索引。
RKI:首先反向每個列鍵值的字節(如123,就被反爲321,新數值在範圍上,比原來那些列值會分佈的更均勻),然後在反向後的數據上進行索引。
非常適用於含有序數的列。(因傳統的B樹,此時往往會產生很多級,而超過4級性能就會很低)

注意:RKI只能用於等於、不等於判斷。其他如>、<、between等會導致無法使用該索引,可能會導致全表掃描。

SQL>create index idx_employee_iem_id on employee(emp_id)
Reverse
Tablespace idx_dbs;

SQL>alter index idx_employee_iem_id rebuild reverse;

1.3.3.7 Index Organized Table
B樹、位圖、反向等索引,直接指向索引基礎表中對應數據行的ID,這是因爲錶行以一種或多或少的隨機方式被分配給表內的塊,因Oracle在存儲行時,並不考慮行的內容。是一種堆疊方式存儲的數據,叫Heap Table(堆表)。
如果希望按一種指定順序來存儲一個表數據,就要使用IOT(索引組織表)。此時把行數據全部存儲在索引本身內。
好處:
1)錶行按索引順序存儲。若用主鍵來訪問表,IOT比傳統表更快。
2)使用B樹時,只需要讀取索引,不需要讀取表,減少了一次I/O。
注意:
1)IOT在將要做索引基礎的那一列上必須有一個主鍵約束。
2)IOT不能含有唯一性約束,或被cluster。

SQL>create table employee_history
(employee_id number primary key,
last_name varchar2(20),
first_name varchar2(20),
title varchar2(30),
hire_date date,
departure_date date)
ORGANIZATION INDEX TABLESPACE idx_dbs --指定表爲IOT
PCTTHRESHOLD 25 --指定真個數據塊保持打開的百分比,必須在0-50之間
INCLUDEING first_name --指定行超過PCTTHRESHOLD時,按那一列把行分解成兩段
OVERFLOW TABLESPACE app_of – 指定分解的行的一半存儲的表空間
MAPPING TABLE; -- 在創建IOT上的位圖所有時所必須的一個關聯映像表的創建

位圖索引可以以堆表(此時以行ID關聯數據行)或IOT(利用映像表來定位被索引的IOT行)做爲基礎表。
映像表:把索引的物理行ID映像到索引組織表的對應的邏輯行ID,每個IOT只有一個。
物理行ID會隨着數據的insert和delete而發生變化(因爲排序了,IOT葉會在它們變滿時像B樹索引一樣發生分裂;如果沒有映像表記錄邏輯ID,這種物理分裂會使相關位圖索引不能使用)。
隨着時間的推移,bitmap index可能會和IOT不一致,查找不一致範圍:
SQL> select owner,index_name,pct_direct_access from dba_indexes
where pct_direct_access is not null;
Oracle建議,超過30%的bitmap index應該rebuild。

1.3.4 分區partition
分區:將表數據劃分成更小的子集。
好處:
1)提高可用性。
如100GB的表,如果劃分成2G的50個分區,只要當前查詢的數據所處的分區online,而其他的分取offline,數據庫依然工作正常。
2)減輕管理負擔。
對分區數據的維護,比如刪除、更新、分析、數據恢復等,可以以分區爲單位進行維護。
3)提高DML和查詢操作性能。
利用CBO的分區排除機制,跳過未含有相關數據的表分區,減少I/O。

分區表使用CBO,CBO具有很好的“分區意識能力”,直接排除不屬於查詢結果的分區。(分區鍵列上同樣不能應用函數,否則不會使用索引)
對於分區的表,應儘可能的利用分區鍵作爲查詢條件,不然會執行full table scan,會比不分區的全表掃描花費更多的時間,失去分區的意義。

分區信息可查詢:select * from user_tab_partitions;

(比如小區表,可以按小時分區,小時裏再按hash分區防止分區不均勻,此時再對各分區進行truncate等維護,就快了)
1.3.4.1 創建分區
分區可分爲如下幾種:(範圍分區,hash分區,列表分區,範圍-hash分區,範圍-列表分區(oracle 9i relase 2以後才提供))
 範圍分區
使用列值的範圍來確定一個數據行被插入到那個分區中。
1)分區鍵最多可16列,一個表最多可65636個分區。
2)分區範圍中不能有任何空隙。
3)每個分區中,等於上限的值都是存儲在上一個分區中的。
4)less then子句指定的值,必須是一個用RPAD函數填充過的值、日期(必須包含世紀)或常數。
5)分區表不能包含帶有long,long raw的數據列。
6)試圖插入一個無法放入任一分區的數據,都導致ORA-14400錯誤。
7)通過更新數據使數據在分區間移動不被允許,除非創建表的時候指定了enable row movement子局。

如果插入的數據導致分區不均勻,應考慮使用散列分區。

SQL>create table student_history
(student_id number(10),
degree varchar2(3),
gradution_date date)
PARTITION BY RANGE (graduation_date)
(PARTION p_2000 VALUES LESS THEN
(to_date(‘2000-1-1’,’yyyy-mm-dd’)) TABLESPACE hist_tab01,
PARTION p_2001 VALUES LESS THEN
(to_date(‘2001-1-1’,’yyyy-mm-dd’)) TABLESPACE hist_tab02,
PARTION p_error VALUES LESS THEN
(MAXVALUE) TABLESPACE hist_tab03
);

SQL> select * from student_history (p_2000);

 列表分區
類似範圍分區,區別是它基於一組指定的值。範圍分區是基於一個範圍。
試圖插入一個無法放入任一分區的數據,都導致ORA-14400錯誤。

SQL>create table student_history
(student_id number(10),
degree varchar2(3),
gradution_date date)
PARTITION BY LIST (degree)
(PARTION p_undergrad VALUES (‘BS’,’BA’,’BBA’,’BFA’)
TABLESPACE hist_tab01,
PARTION p_graduate VALUES (‘MA’,’MBA’,’MFA’,’MS’)
TABLESPACE hist_tab02,
PARTION p_doctorate VALUES (‘PHD’)
TABLESPACE hist_tab03
);

 散列分區
使用一個散列算法來分配數據被插入到那個分區中。一般分配很均勻,對於序數的列很適合。
1)分區鍵應具有很高基數。
2)如果是唯一鍵分區,效果最好。如果是範圍查找,不會有性能提升。
3)通過更新數據使數據在分區間移動不被允許。
4)總分區數,應該是2的整數倍。

SQL> create table student_history
(student_id number(10),
degree varchar2(3),
gradution_date date)
PARTITION BY HASH (student_id)
PARTITION 3
STORE IN (hist_tab01, hist_tab02, hist_tab03);

drop table part_ALARMTEXTDATA;
create table part_ALARMTEXTDATA
( ALARMNUMBER VARCHAR2(16) NOT NULL ,
ALARMTEXT VARCHAR2(255) NOT NULL ,
SERIAL NUMBER(38) NOT NULL)
PARTITION BY HASH (ALARMNUMBER)
(part_ALARMTEXTDATA_01 tablespace hxj_partion01,
part_ALARMTEXTDATA_02 tablespace hxj_partion02,
part_ALARMTEXTDATA_03 tablespace hxj_partion03,
part_ALARMTEXTDATA_04 tablespace hxj_partion04);

 組合分區
創建範圍分區,在該分區內又再創建散列分區。(一般用在需要範圍分區,而範圍分區又不均勻的情況下)
1)分區是邏輯結構,表數據被存儲在子分區級上。
2)組合分區對:分區級的、歷史的、日期的,查詢十分好使。
3)組合分區對子分區級的並行操作也十分有用。
4)分區級的連接操作通過使用組合的局部索引支持。

SQL> create table student_history
(student_id number(10),
degree varchar2(3),
gradution_date date)
PARTITION BY RANGE (graduation_date)
SUBPARTITION BY HASH (student_id)
SUBPARTITIONS 2
STORE IN (hist_tab01, hist_tab02)
(
PARTION p_2000 VALUES LESS THEN
(to_date(‘2000-1-1’,’yyyy-mm-dd’)) TABLESPACE hist_tab01,
PARTION p_2001 VALUES LESS THEN
(to_date(‘2001-1-1’,’yyyy-mm-dd’)) TABLESPACE hist_tab02,
PARTION p_error VALUES LESS THEN
(MAXVALUE) TABLESPACE hist_tab03
);

1.3.4.2 索引分區
唯一所以必須是全局的。
分兩類,全局與局部索引,前綴與非前綴索引。
 全局與局部索引:與該索引的分區結構是否與被索引基礎表結構匹配有關係。
局部索引:索引中的分區與基礎表的分區逐個匹配。
- 可以人任何分區上創建局部分區索引。
- 創建後,Oracle自動維護表分區與索引分區之間的關係。
- 分區上的位圖索引必須是局部的索引。
SQL> create index dinya_idx_t on dinya_test(item_id)
local
(
partition idx_1 tablespace dinya_space01,
partition idx_2 tablespace dinya_space02,
partition idx_3 tablespace dinya_space03
);
Index created.
SQL>

全局索引:索引中的分區與基礎表的分區數不逐個匹配。
- 可以人任何分區上創建全局分區索引,但它自身必須是範圍的。
- 最高分區必須以MAXVALUE參數來定義。
- 對分區表的維護操作(drop ,truncate操作等),會導致全局索引無效。此時必須重建。
- 使用global創建與表分區一樣多的索引,Oracle也不會認爲是局部索引。
SQL> create index dinya_idx_t on dinya_test(item_id)
global partition by range(item_id)
(
partition idx_1 values less than (1000) tablespace dinya_space01,
partition idx_2 values less than (10000) tablespace dinya_space02,
partition idx_3 values less than (maxvalue) tablespace dinya_space03
);
Index created.
global 子句允許指定索引的範圍值,這個範圍值爲索引字段的範圍值.
SQL>

SQL> create index dinya_idx_t on dinya_test(item_id);
Index created.
SQL>

 前綴與非前綴索引:與該索引是否有分區鍵及分區鍵出現在索引結構內的位置有關係。
前綴索引:索引的最左列與分區鍵相同。可以是唯一的,也可以不是唯一的。
前綴局部索引:
SQL>create index student_history_lp_idx on student_history (graduation_date) local;
此時默認與基礎表分區數一樣。以graduation_date範圍分區。
前綴全局索引:
略。
非前綴索引:索引的最左列與分區鍵不相同。可以是唯一的(唯一時分區鍵必須是索引的子集),也可以不是唯一的。
非前綴局部索引:
SQL>create index student_history_lp_idx on student_history (graduation_date) local;
此時默認與基礎表分區數一樣。以graduation_date範圍分區。
非前綴全局索引:
略。

分區索引不能作爲整體一次重建。
alter index local2_alarminfo rebuild partition l_ind2_alarminfo_050915;

1.3.4.3 管理分區
1.1.1.1.1 收集分區的統計數據
可以針對段、分區或子分區級上收集。
例(收集分區表和分區索引):
SQL>execute dbms_stats.gather_table_stats(ownname=>’APPS’,tabname=>’STUDENT_HISTORY’,partname=>’P_1998’,granularity=>’PARTITION’);

SQL>execute dbms_stats.gather_index_stats(ownname=>’SYS’,indname=>’STUDENT_HISTORY_GP_IDX’,partname=>’P_200n’);


[url]http://hi.baidu.com/zting0103/blog/item/0b42b029885097fd98250a63.html[/url]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章