日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

oracle索引使用例子,Oracle中利用函数索引处理数据倾斜案例

發布時間:2023/12/10 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 oracle索引使用例子,Oracle中利用函数索引处理数据倾斜案例 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

關于B-Tree、Bitmap、函數索引的相關內容請參考另一篇博文:

Oracle中B-Tree、Bitmap和函數索引使用案例總結

通常來說,索引選取的數據列最好為分散度高、選擇性好。從索引樹結構的角度看,列值都是分布在葉節點位置。這樣,通過樹結構搜索得到的葉節點數量效率比較高。

實際中,我們常常遇到數據列值傾斜的情況。就是說,整個列數據取值有限。但是大部分數據值都集中在少數一兩個取值里,其他取值比例極少。比如:一個數據列值有“N”、“B”、“M”、“P”、“Q”幾個取值,其中55%數據行取值為“N”,40%數據行取值為“B”,剩下的取值分布在5%的數據行中。對于這種結構的數據列加索引,是存在一些問題的。

首先,默認數據庫是會為所有的列值(非空)建立索引結構。也就意味著無論是高頻度取值,還是低頻度取值,都會在索引結構的葉節點上出現。當然,這樣的大部分葉節點都是這些重復值。

其次,在CBO(基于成本優化器)的作用下,對高頻度取值的搜索一般都不會選擇索引作為搜索路徑,因為進行全表掃描可能效率更高。我們為數據列建立了索引,但高頻詞的查詢永遠不會走到索引路徑(下面的實驗會證明這一點)。

最后,建立的索引空間和時間消耗比較大。建立的索引涵蓋所有取值,對海量數據表而言,占有的空間勢必較大。同時,在進行小頻度數據查詢的時候,雖然會去走索引路徑,但是引起的邏輯物理讀也是有一些損耗。

下面引入一個解決方法

思路:既然高頻度值在查詢的時候不會走到索引路徑,可以考慮將其剔出構建索引的過程,只為那些低頻度數據值建立索引結構。這樣,建立的索引樹結構相對較小,而且索引查詢的效率也能提升。

具體的方法是使用decode函數。decode(a,b,c,d,e…f)含義:如果a=b,則返回c,等于d,返回e,最后沒有匹配的情況下,返回f。針對上面的例子,可以使用decode(列名,‘N’, null,‘B’,null,列名),含義是,如果該列取值為N或者B,直接設置為null,否則才返回列值,并且以此建立函數索引。

這樣做借助了Oracle兩個功能:1、對null值不生成索引;2、函數索引;

下面通過實驗來證明該方法:

1、構建實驗測試環境

--創建測試數據表tb_wjq

SEIANG@seiang11g>create table tb_wjq as select * from dba_objects where owner

in ('SEIANG','PUBLIC','HR','SYSMAN','XDB','BI','SYS');

Table created.

--使用腳本插入大量數據

begin

for i in 1..8 loop

insert /*+ append */ into tb_wjq select * from tb_wjq;

commit;

end loop;

end;

/

SEIANG@seiang11g>select count(*) from tb_wjq;

COUNT(*)

----------

9804160

Elapsed: 00:00:01.54

--用于實驗的數據量分布情況

SEIANG@seiang11g>select owner,count(*) from tb_wjq group by owner;

OWNER??????????????????????????? COUNT(*)

------------------------------ ----------

SEIANG?????????????????????????????? 3072

PUBLIC??????????????????????????? 4352256

HR?????????????????????????????????? 4352

SYSMAN???????????????????????????? 454912

XDB??????????????????????????????? 149760

BI?????????????????????????????????? 1024

SYS?????????????????????????????? 4838784

7 rows selected.

Elapsed: 00:00:02.44

可以看到,九萬多條數據,絕大部分數據集中到了PUBLIC、SYSMAN、SYS上,其他數據取值頻數較小。數據傾斜趨勢明顯。

2、建索引

--分別對owner列建立常規、函數索引。

SEIANG@seiang11g>create index idx_tb_wjq_owner_normal on tb_wjq(owner);

Index created.

Elapsed: 00:00:24.72

SEIANG@seiang11g>create index func_idx_tb_wjq_owner on tb_wjq(decode

(owner,'PUBLIC',null,'SYSMAN',null,'SYS',null,owner));

Index created.

Elapsed: 00:00:12.34

索引func_idx_tb_wjq_owner將PUBLIC、SYSMAN、SYS值轉化為null,剔出了建立索引的過程。不僅可以從上面創建索引所用的時間可以看出,而且從下面的索引段信息看,兩個索引所占的空間差異比較大,也證明了這點。

SEIANG@seiang11g>select

owner,segment_name,segment_type,bytes/1024/1024,blocks,extents from

dba_segments where segment_name='IDX_TB_WJQ_OWNER_NORMAL';

OWNER?????????? SEGMENT_NAME?????????????????? SEGMENT_TYPE?????? BYTES/1024/1024???? BLOCKS

EXTENTS

--------------- ------------------------------ ------------------

--------------- ---------- ----------

SEIANG????????? IDX_TB_WJQ_OWNER_NORMAL??????? INDEX????????????????????????? 184????? 23552???????? 94

Elapsed: 00:00:00.01

SEIANG@seiang11g>select

owner,segment_name,segment_type,bytes/1024/1024,blocks,extents from

dba_segments where segment_name='FUNC_IDX_TB_WJQ_OWNER';

OWNER?????????? SEGMENT_NAME?????????????????? SEGMENT_TYPE?????? BYTES/1024/1024???? BLOCKS

EXTENTS

--------------- ------------------------------ ------------------

--------------- ---------- ----------

SEIANG

FUNC_IDX_TB_WJQ_OWNER????????? INDEX??????????????????????????? 3??????? 384???????? 18

由上可以看出,同樣是對一個數據列加索引。普通索引類型IDX_TB_WJQ_OWNER_NORMAL占據94個區,23552個數據塊,空間約占184M。而函數索引FUNC_IDX_TB_WJQ_OWNER的空間只用了初始分配的18個區,384個數據塊,空間約占3M。由此,空間優勢直觀體現!

--收集統計數據,由于是實驗性質,而且數據量大,采用高采樣率收集統計信息。

SEIANG@seiang11g>exec dbms_stats.gather_table_stats('SEIANG', 'TB_WJQ',

cascade => true, estimate_percent => 100,method_opt => 'for all

indexed columns');

PL/SQL procedure successfully completed.

Elapsed: 00:00:49.67

3、檢索效率分析

針對owner數據量149760的XDB取值進行分析。

--直接索引搜索:

SEIANG@seiang11g>select * from tb_wjq where owner='XDB';

149760 rows selected.

Elapsed: 00:00:01.89

Execution Plan

----------------------------------------------------------

Plan hash value: 3735191644

-------------------------------------------------------------------------------------------------------

| Id? | Operation?????????????????? | Name??????????????????? | Rows? | Bytes | Cost (%CPU)| Time???? |

-------------------------------------------------------------------------------------------------------

|?? 0 | SELECT STATEMENT??????????? |???????????????????????? |?? 149K|

13M|? 4708?? (1)| 00:00:57 |

|?? 1 |

TABLE ACCESS BY INDEX ROWID| TB_WJQ????????????????? |?? 149K|

13M|? 4708?? (1)| 00:00:57 |

|*? 2 |INDEX RANGE SCAN????????? | IDX_TB_WJQ_OWNER_NORMAL|?? 149K|?????? |

348?? (1)| 00:00:05 |

-------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

2 - access("OWNER"='XDB')

Statistics

----------------------------------------------------------

8? recursive calls

0? db block gets

26000

consistent gets

6349? physical reads0? redo size

16482673? bytes sent via SQL*Net to client

110336? bytes received via SQL*Net from client

9985? SQL*Net roundtrips to/from client

0? sorts (memory)

0? sorts (disk)

149760? rows processed

發現采用BI作為搜索值時,是進行了索引搜索。下面是用函數索引搜索進行對比。

SEIANG@seiang11g>select * from tb_wjq where decode

(owner,'PUBLIC',null,'SYSMAN',null,'SYS',null,owner)='XDB';

149760 rows selected.

Elapsed: 00:00:01.54

Execution Plan

----------------------------------------------------------

Plan hash value: 3652333940

-----------------------------------------------------------------------------------------------------

| Id? | Operation?????????????????? | Name????????????????? | Rows? | Bytes | Cost (%CPU)| Time???? |

-----------------------------------------------------------------------------------------------------

|?? 0 | SELECT STATEMENT??????????? |?????????????????????? |?? 149K|

13M|? 7091?? (1)| 00:01:26 |

|?? 1 |

TABLE ACCESS BY INDEX ROWID| TB_WJQ??????????????? |?? 149K|

13M|? 7091?? (1)| 00:01:26 |

|*? 2 |INDEX

RANGE SCAN????????? |

FUNC_IDX_TB_WJQ_OWNER|

149K|?????? |?? 316

(1)| 00:00:04 |

-----------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

2 -

access(DECODE("OWNER",'PUBLIC',NULL,'SYSMAN',NULL,'SYS',NULL,"OWNER")='XDB')

Statistics

----------------------------------------------------------

0? recursive calls

0? db block gets

25998

consistent gets

0? physical reads0? redo size

9017261 ?bytes sent via SQL*Net to client

110336? bytes received via SQL*Net from client

9985? SQL*Net roundtrips to/from client

0? sorts (memory)

0? sorts (disk)

149760? rows processed

對比后,我們可以發現,使用函數索引的方法,在執行時間、物理邏輯讀、CPU使用上有一定差異。

普通索引

函數索引

執行時間

00: 00: 01.89

00: 00: 01.54

CPU使用

4708

7091

consistent gets

26000

25998

physical reads

6349

0

結論:使用函數索引處理偏值方法,在一定長度上優化查詢效率和索引結構。上表的數據表明,會使邏輯物理讀的消耗很大程度的減少(索引結構簡化),同時連帶影響執行時間的縮小。因為使用函數要進行計算,CPU使用率相對較高,在可以接受的范圍內。

但是,這種方法是存在一些限制的,應用前一定要仔細規劃。

首先,數據表數據要保證較大。因為畢竟函數索引的建立和搜索較普通索引消耗大,如果數據表小,帶來的優化程度不能彌補消耗的成本,結果可能得不償失。筆者進行的一系列實驗中,也發現在數據量中等偏小時,這種性能優勢不能凸顯。

其次,列值傾斜趨勢明顯。通過開篇的討論我們不難發現,列值傾斜的程度越高,使用函數索引剔出的數據量也就越大,生成的索引樹結構也就越小越優化。這一點是本方法的核心!

最后,使用函數索引搜索時,搜索的取值頻數越高,優化效果越好。在本例中,取值XDB的列有149760行,可以看出明顯的性能優化。但是當我們選擇值有1024條數據的BI值時,這種優化趨勢可以看到,但是明顯程度降低(實驗結果如下所示)。這里的原因可能是數據量小時,兩種方法邏輯物理讀的差異度縮小。

--直接索引

SEIANG@seiang11g>select * from tb_wjq where owner='BI';

1024 rows selected.

Elapsed: 00:00:00.03

Execution Plan

----------------------------------------------------------

Plan hash value: 3735191644

-------------------------------------------------------------------------------------------------------

| Id? | Operation?????????????????? | Name??????????????????? | Rows? | Bytes | Cost (%CPU)| Time???? |

-------------------------------------------------------------------------------------------------------

|?? 0 | SELECT STATEMENT??????????? |???????????????????????? |? 1024 |

98K|??? 35?? (0)| 00:00:01 |

|?? 1 | ?TABLE ACCESS BY INDEX ROWID| TB_WJQ????????????????? |? 1024 |

98K|??? 35?? (0)| 00:00:01 |

|*? 2 |INDEX

RANGE SCAN????????? |

IDX_TB_WJQ_OWNER_NORMAL|

1024 |?????? |???? 5

(0)| 00:00:01 |

-------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

2 - access("OWNER"='BI')

Statistics

----------------------------------------------------------

0? recursive calls

0? db block gets

280? consistent gets

151? physical reads0? redo size

98579? bytes sent via SQL*Net to client

1271? bytes received via SQL*Net from client

70? SQL*Net roundtrips to/from client

0? sorts (memory)

0? sorts (disk)

1024? rows processed

--函數索引

SEIANG@seiang11g>select * from tb_wjq where decode

(owner,'PUBLIC',null,'SYSMAN',null,'SYS',null,owner)='BI';

1024 rows selected.

Elapsed: 00:00:00.01

Execution Plan

----------------------------------------------------------

Plan hash value: 3652333940

-----------------------------------------------------------------------------------------------------

| Id? | Operation?????????????????? | Name????????????????? | Rows? | Bytes | Cost (%CPU)| Time???? |

-----------------------------------------------------------------------------------------------------

|?? 0 | SELECT STATEMENT??????????? |?????????????????????? |? 1024 |

98K|??? 50?? (0)| 00:00:01 |

|?? 1 |

TABLE ACCESS BY INDEX ROWID| TB_WJQ??????????????? |? 1024 |

98K|??? 50?? (0)| 00:00:01 |

|*? 2 |INDEX

RANGE SCAN????????? |

FUNC_IDX_TB_WJQ_OWNER|? 1024

|?????? |???? 3

(0)| 00:00:01 |

-----------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

2 -

access(DECODE("OWNER",'PUBLIC',NULL,'SYSMAN',NULL,'SYS',NULL,"OWNER")='BI')

Statistics

----------------------------------------------------------

0? recursive calls

0? db block gets

279

consistent gets

3? physical reads0? redo size

33969? bytes sent via SQL*Net to client

1271? bytes received via SQL*Net from client

70? SQL*Net roundtrips to/from client

0? sorts (memory)

0? sorts (disk)

1024? rows processed

但是如果是對SYS、PUBLIC或SYSMAN進行查詢時,將會跳過所有的索引,直徑進行全表掃描。

SEIANG@seiang11g>select * from tb_wjq where owner='SYS';

4838784 rows selected.

Elapsed: 00:00:45.85

Execution Plan

----------------------------------------------------------

Plan hash value: 1501781665

----------------------------------------------------------------------------

| Id? | Operation???????? | Name?? | Rows

| Bytes | Cost (%CPU)| Time???? |

----------------------------------------------------------------------------

|?? 0 | SELECT STATEMENT? |

|? 4838K|?? 452M| 39893

(1)| 00:07:59 |

|*? 1 |TABLE

ACCESS FULL| TB_WJQ|

4838K|?? 452M| 39893?? (1)| 00:07:59 |

----------------------------------------------------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

1 - filter("OWNER"='SYS')

Statistics

----------------------------------------------------------

8? recursive calls

0? db block gets

457638? consistent gets

139684? physical reads0? redo size

255169095? bytes sent via SQL*Net to client

3548958? bytes received via SQL*Net from client

322587? SQL*Net roundtrips to/from client

0? sorts (memory)

0? sorts (disk)

4838784? rows processed

作者:SEian.G(苦練七十二變,笑對八十一難)

總結

以上是生活随笔為你收集整理的oracle索引使用例子,Oracle中利用函数索引处理数据倾斜案例的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。