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(苦练七十二变,笑对八十一难)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/410909.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[html] canvas生成图片有没有跨域问题?如果有如何解决?

[html] canvas生成图片有没有跨域问题?如果有如何解决? 前端设置 useCORS: true。后台配置允许跨域个人简介 我是歌谣,欢迎和大家一起交流前后端知识。放弃很容易, 但坚持一定很酷。欢迎大家一起讨论 主目录 与歌谣一起通关前…

什么是SSID/ESSID/BSSID

什么是SSID/ESSID/BSSID? SSID(Service Set Identifier)AP唯一的ID码,用来区分不同的网络,最多可以有32个字符,无线终端和AP的SSID必须相同方可通信。无线网卡设置了不同的SSID就可以进入不同网络&#xff…

Oracle数据文件scn不一致,数据文件SCN的一致性问题

1、数据库正常运行中,所有数据文件的SCN都是一致的吗?2、将一数据文件offline后,再将其online时,这个数据文件的SCN会前提吗?假如是,前提到的SCN是怎么确定的?1.数据库正常运行时,所…

[html] 如何垂直居中<img>?

[html] 如何垂直居中? 使用协助元素(这里是i),作为img的相邻元素,同为inline-block的两元素相邻时增加vertical-align: middle个人简介 我是歌谣,欢迎和大家一起交流前后端知识。放弃很容易, …

Acess 数据库 查询数据表结构等问题小记

今天一次性解决三个小问题: 问题1:本机打开Access数据库老是提示:“Windows 正在配置 Microsoft Office Professional Edition 2003,请稍候” 解决办法: 手动更改注册表步骤操作: 1. 单击“开始”&#xff…

集合计数 (容斥原理)

心路: { 想了个思路打出来硬干掉了样例,然后发现是错的....当时直接崩了...烦躁滴很...其实这个思路和题解大方向上是一样的,想到了用至少含k个的方案数减去含k1个的加上k2的。。。 然后再想怎么求至少含k个的方案数想到了让集合含这k个数然后随机组就行…

[html] 如何禁止手机端页面缩放?

[html] 如何禁止手机端页面缩放&#xff1f; <meta name"viewport" content"user-scalableno">个人简介 我是歌谣&#xff0c;欢迎和大家一起交流前后端知识。放弃很容易&#xff0c; 但坚持一定很酷。欢迎大家一起讨论 主目录 与歌谣一起通关前…

oracle 执行计划 ppt,oracle查看执行计划的方法

查看执行计划的方法Explain Plan For SQL不实际执行SQL语句&#xff0c;生成的计划未必是真实执行的计划必须要有plan_tableSQLPLUS AUTOTRACE除set autotrace traceonly explain外均实际执行SQL&#xff0c;但仍未必是真实计划必须要有plan_tableSQL TRACE需要启用10046戒者SQ…

《TCP/IP Sockets 编程》笔记5

第5章 发送和接收数据 There is nomagic: any programs that exchange information must agree on how that information will be encoded—represented as a sequence of bits—as well as which program sends what information when, and how the information received affe…

codeforces-1176 (div3)

打div3翻车了 A.第一个操作是除二&#xff0c;第二个操作视为两下操作之后除三&#xff0c;第三个操作视为三下操作之后除五&#xff0c;直接计算贡献 #include <map> #include <set> #include <ctime> #include <cmath> #include <queue> #incl…

oracle的工具cmd,数据库命令行工具DBCLI

转换日期有点问题。column trans_low format a20column trans_high format a20column data_default format a20SELECT--owner,-- table_name,column_name,data_type,data_length,nullable,num_distinct,density,sample_size,CASEWHEN data_type IN (CHAR, VARCHAR2)THE…

[html] 你能否画出一个0.5px的直线?

[html] 你能否画出一个0.5px的直线&#xff1f; 通过scale(0.5)来实现个人简介 我是歌谣&#xff0c;欢迎和大家一起交流前后端知识。放弃很容易&#xff0c; 但坚持一定很酷。欢迎大家一起讨论 主目录 与歌谣一起通关前端面试题

VS2008 正式版 下载+ KEY 注册码

微软官方下载 http://www.microsoft.com/downloads/details.aspx?displaylangzh-cn&FamilyIDd95598d7-aa6e-4f24-82e3-81570c5384cb 中文 MSDN Library for Visual Studio 2008 http://www.microsoft.com/downloads/details.aspx?displaylangzh-cn&FamilyID6ff3bc60-…

微软CRM 2011 Beta 新功能之二:不同组织不同基本语言

微软CRM 4.0就开始提供对多语言的支持&#xff0c;在安装微软CRM 4.0时需要选择不同语言的安装程序&#xff0c;安装完成后该部署服务器上默认组织以及任何新建组织的基本语言跟安装程序的语言一致。虽然我们可以在服务器上安装多个语言包&#xff0c;使用户可以选择要使用的语…

php教育项目,六星教育:如何在PHP项目实战中取胜,获得腾讯等大厂的offer

原标题&#xff1a;六星教育&#xff1a;如何在PHP项目实战中取胜&#xff0c;获得腾讯等大厂的offer我们在进行PHP学习的时候&#xff0c;总会强调实战的重要性。事实也是如此&#xff0c;如果光知道理论知识&#xff0c;而缺乏实际项目的参与与运作&#xff0c;就会变得纸上谈…

[html] 制作一个页面时,需要兼容PC端和手机端,你是要分别做两个页面还是只做一个页面自适应?为什么?说说你的理由

[html] 制作一个页面时&#xff0c;需要兼容PC端和手机端&#xff0c;你是要分别做两个页面还是只做一个页面自适应&#xff1f;为什么&#xff1f;说说你的理由 两个页面 pc端布局和交互行为跟移动端不一样&#xff0c; 两个页面反而更好维护个人简介 我是歌谣&#xff0c;欢…

Silverlight学习笔记(一)——Silverlight够酷吗?

2007年底&#xff0c;微软推出了Silverlight1.0&#xff0c;在RIA领域小试牛刀。如今&#xff0c;Silverlight的成长速度已经超过了人们当初的想象。其一体化的编程方式、与JavaScript和Asp.Net的无缝集成功能&#xff0c;强大的应用层美工、设计工具&#xff0c;已经让众多开发…

方法有多少个参数才算多?

小弟有这样一个方法&#xff0c;按页大小和页索引查询产品&#xff0c;如下。 ///<summary>///获取产品///</summary>///<param name"manufacturerID">厂商ID&#xff0c;为null时不做查询条件。</param>///<param name"categoryID&…

[html] 如何实现页面背景图固定不动,不跟随滚动条滚动?

[html] 如何实现页面背景图固定不动&#xff0c;不跟随滚动条滚动&#xff1f; background-attachment: fixed个人简介 我是歌谣&#xff0c;欢迎和大家一起交流前后端知识。放弃很容易&#xff0c; 但坚持一定很酷。欢迎大家一起讨论 主目录 与歌谣一起通关前端面试题

oracle数据库纵表设计,oracle 数据库设计-数据库表设计

在数据库设计中&#xff0c;我的工作中经常会分析怎样商业逻辑中的表格如何设计。再设计表的关系之前 需要先了解关系型数据库特点1关系型数据库&#xff0c;是指采用了关系模型来组织数据的数据库&#xff1b;2、关系型数据库的最大特点就是事务的一致性&#xff1b;3、简单来…