oracle分区表、索引、绑定变量等速度测试

数据库实验

一.实验环境

1.    系统:win7 64位(虚拟机)

2.    处理器:Inter(R)Core(TM)i5-6267U [email protected]

3.    内存:4G

4.    数据库:oracle 12c

5.    运行SQL环境:navicat 和sql plus

二.实验数据

1.      数据来源:tpc-h数据集

2.      数据详情:

一共有8张表分别是(数据量从小到大):

(1)  Region表             5条数据

类型

长度

含义

是否null

R_REGIONKEY

NUMBER

0

地区key值

NOT NULL

R_NAME

CHAR

25

地区名

NOT NULL

R_COMMENT

VARCHAR

152

地区细节

 

 

(2)    Nation表                       25条数据

类型

长度

含义

不是null

N_NATIONKEY   

INTEGER

0

国家key值

NOT NULL

N_NAME        

CHAR

25

国家名

NOT NULL

N_REGIONKEY   

INTEGER

0

所属地区key值

NOT NULL

N_COMMENT    

VARCHAR

152

国家细节

 

 

(3)    Supplier表                    10000

类型

长度

含义

不是null

S_SUPPKEY      

INTEGER

0

供应商key值

NOT NULL

S_NAME         

CHAR

25

供应商名

NOT NULL

S_ADDRESS     

VARCHAR

40

供应商地址

NOT NULL

S_NATIONKEY    

INTEGER

0

供应商国家key

NOT NULL

S_PHONE       

CHAR

15

供应商电话

NOT NULL

S_ACCTBAL     

DECIMAL (15,2)

15

账户结余

NOT NULL

S_COMMENT     

VARCHAR

101

细节

NOT NULL

 

(4)    Part表                            20

           

类型

长度

含义

不是null

P_PARTKEY      

INTEGER

0

零件key值

NOT NULL

P_NAME        

VARCHAR(55) 

55

零件名

NOT NULL

P_MFGR         

CHAR

25

供应商名

NOT NULL

P_BRAND        

CHAR

10

品牌

NOT NULL

P_TYPE        

VARCHAR 

25

零件类型

NOT NULL

P_SIZE         

INTEGER

0

大小

NOT NULL

P_CONTAINER    

CHAR

10

容器货柜

NOT NULL

P_RETAILPRICE 

DECIMAL(15,2) 

15

零售价

NOT NULL

P_COMMENT     

VARCHAR 

23

细节

NOT NULL

 

(5)    Customer表                            15

类型

长度

含义

不是null

C_CUSTKEY      

INTEGER

0

消费者key值

NOT NULL

C_NAME        

VARCHAR

25

消费者名

NOT NULL

C_ADDRESS      

VARCHAR

40

消费者地址

NOT NULL

C_NATIONKEY    

INTEGER

0

消费者国家key

NOT NULL

C_PHONE        

CHAR

15

消费者电话

NOT NULL

C_ACCTBAL       

DECIMAL(15,2) 

15

消费者账户结余

NOT NULL

C_MKTSEGMENT   

CHAR

10

市场划分

NOT NULL

C_COMMENT      

VARCHAR

117

细节

NOT NULL

 

(6)    Partsupp表                             80

类型

长度

含义

不是null

PS_PARTKEY      

INTEGER

0

零件key

NOT NULL

PS_SUPPKEY      

INTEGER

0

供应商key

NOT NULL

PS_AVAILQTY     

INTEGER

0

平均数量

NOT NULL

PS_SUPPLYCOST    

DECIMAL(15,2)

15

供应成本

NOT NULL

PS_COMMENT      

VARCHAR

199

细节

NOT NULL

 

(7)    Orders表                                 150万条

类型

长度

含义

不是null

O_ORDERKEY        

INTEGER

0

订单key

NOT NULL

O_CUSTKEY         

INTEGER

0

消费者key

NOT NULL

O_ORDERSTATUS     

CHAR

1

订单状态

NOT NULL

O_TOTALPRICE     

DECIMAL(15,2) 

15

订单总价

NOT NULL

O_ORDERDATE       

DATE

 

订单日期

NOT NULL

O_ORDERPRIORITY   

CHAR

15

订单优先级

NOT NULL

O_CLERK           

CHAR

15

销售员

NOT NULL

O_SHIPPRIORITY    

INTEGER

0

发货优先级

NOT NULL

O_COMMENT        

VARCHAR

79

细节

NOT NULL

 

(8)    Lineitem表(在线商品)                            6,001,215

类型

长度

含义

不是null

L_ORDERKEY     

INTEGER

0

订单key

NOT NULL

L_PARTKEY      

INTEGER

0

零件key

NOT NULL

L_SUPPKEY      

INTEGER

0

供应商key

NOT NULL

L_LINENUMBER   

INTEGER

0

在线号码

NOT NULL

L_QUANTITY    

DECIMAL(15,2) 

15

数量

NOT NULL

L_EXTENDEDPRICE   

DECIMAL(15,2)

15

折扣价

NOT NULL

L_DISCOUNT    

DECIMAL(15,2) 

15

折扣

NOT NULL

L_TAX         

DECIMAL(15,2) 

15

NOT NULL

L_RETURNFLAG   

CHAR

1

 

NOT NULL

L_LINESTATUS   

CHAR

1

在线状态

NOT NULL

L_SHIPDATE    

DATE 

 

发货日期

NOT NULL

L_COMMITDATE  

DATE 

 

提货日期

NOT NULL

L_RECEIPTDATE  

DATE

 

接收日期

NOT NULL

L_SHIPINSTRUCT  

CHAR

25

装运指示

NOT NULL

L_SHIPMODE      

CHAR

10

运输形式

NOT NULL

L_COMMENT      

VARCHAR

44

细节

NOT NULL

3.      表结构关系图

4.      TPC-H标准定义的模式图

三.分区表实验(实验一)

1.     分区表:当表中的数据量不断增大,查询数据的速度就会变慢,应用程序的性能就会下降,这时就应该考虑对表进行分区。表进行分区后,逻辑上表仍然是一张完整的表,只是将表中的数据在物理上存放到多个表空间(物理文件上),这样查询数据时,不至于每次都扫描整张表。

2.  分区表优点:

(1)  改善查询性能:对分区对象的查询可以仅搜索自己关心的分区,提高检索速度。

(2)  增强可用性:如果表的某个分区出现故障,表在其他分区的数据仍然可用;

(3)  维护方便:如果表的某个分区出现故障,需要修复数据,只修复该分区即可;

(4)    均衡I/O:可以把不同的分区映射到磁盘以平衡I/O,改善整个系统性能。

3.     问题汇总

(1)没有建分区表前的速度?建好分区表之后的性能?不同分区方法?

(2)为什么他快?

(3)新增问题:

在建表时候没有使用分区表怎么办?普通表如何转化为分区表?

4.     分区实验

(1)使用的表是:ORDERS(150万条数据)

(2)测试的sql语句

1.SELECT *FROM ORDERS WHERE O_TOTALPRICE>10000;

2.SELECT *FROM ORDERS WHERE O_ORDERDATE

between to_date('1994-01-01 00:00:00','yyyy-mm-dd hh24:mi:ss') 

and to_date('1995-12-31 00:00:00','yyyy-mm-dd hh24:mi:ss');

3.     SELECT *FROM ORDERS WHERE O_ORDERKEY>100000 AND O_CUSTKEY<200000;

4.     SELECT *FROM ORDERS WHERE O_ORDERSTATUS='O';

5.     SELECT *FROM ORDERS WHERE O_CLERK LIKE 'Clerk#0000003%';

(3)分区表sql:

(4)对比图:      单位:秒       第一格为第一次查询结果,第二格是第二次的结果

Sql语句

没有建立分区表的速度

建立时间分区表的速度

建立hash分区表的速度

sql语句1

37.781

29.163

27.242

23.529

26.157

22.358

sql语句2

8.5000

8.001

7.816

7.798

10.408

8.039

sql语句3

24.611

23.906

23.872

23.255

24.075

23.078

sql语句4

11.673

13.214

11.280

11.713

11.354

11.298

Sql语句5

3.433

2.813

3.228

3.104

3.133

3.028

5.     原因分析

(1)为什么他快?

在测试完之后,并没有感觉快多少,甚至,hash分区的效率甚至不如没有建立分区表;分区表的本质应该是降低I/O。

(2)在建表时候没有使用分区表怎么办?普通表如何转化为分区表?

在做这个实验的时候发现一开始不是很理解是怎么做,一开始以为是在原表的基础上做分区表,后来发现并不是这样,但是当原表没有建立分区表的时候也是可以补救的。

普通表转化为分区表:

1.       Export/import method

这种方法就是使用insert 来实现。 当然在创建分区表的时候可以一起插入数据,也可以创建好后在insert 进去。 这种方法采用DDL语句,不产生UNDO,只产生少量REDO,建表完成后数据已经在分布到各个分区中。

2.      Insert with a subquery method

利用原表重建分区表,这种方法的特点是:

优点:方法简单易用,由于采用DDL语句,不会产生UNDO,且只产生少量REDO,效率相对较高,而且建表完成后数据已经在分布到各个分区中了。

不足:对于数据的一致性方面还需要额外的考虑。由于几乎没有办法通过手工锁定T表的方式保证一致性,在执行CREATE TABLE语句和RENAME T_NEW TO T语句直接的修改可能会丢失,如果要保证一致性,需要在执行完语句后对数据进行检查,而这个代价是比较大的。另外在执行两个RENAME语句之间执行的对T的访问会失败。

适用于修改不频繁的表,在闲时进行操作,表的数据量不宜太大。 

主要有2种方式,ctas和insert方式

3.      Partition exchange method

利用交换分区的方法这种方法的特点

优点:只是对数据字典中分区和表的定义进行了修改,没有数据的修改或复制,效率最高。如果对数据在分区中的分布没有进一步要求的话,实现比较简单。在执行完RENAME操作后,可以检查T_OLD中是否存在数据,如果存在的话,直接将这些数据插入到T中,可以保证对T插入的操作不会丢失。

不足:仍然存在一致性问题,交换分区之后RENAME T_NEW TO T之前,查询、更新和删除会出现错误或访问不到数据。如果要求数据分布到多个分区中,则需要进行分区的SPLIT操作,会增加操作的复杂度,效率也会降低。

      适用于包含大数据量的表转到分区表中的一个分区的操作。应尽量在闲时进行操作

4.      DBMS_REDEFINITION

利用在线重定义这种分区的特点

优点:保证数据的一致性,在大部分时间内,表T都可以正常进行DML操作。只在切换的瞬间锁表,具有很高的可用性。这种方法具有很强的灵活性,对各种不同的需要都能满足。而且,可以在切换前进行相应的授权并建立各种约束,可以做到切换完成后不再需要任何额外的管理操作。

      不足:实现上比上面两种略显复杂。

 适用于各种情况。 

在线重定义的大致操作流程如下:

       (1)创建基础表A,如果存在,就不需要操作。

       (2)创建临时的分区表B结构。

       (3)开始重定义,将基表A的数据导入临时分区表B。

       (4)结束重定义,完成后在DB的Name Directory里,已经将2个表进行了交换。即此时基表A成了分区表,我们创建的临时分区表B 成了普通表。 此时我们可以删除我们创建的临时表B。它已经是普通表。

 

 

 

四.索引实验(实验二)

1.索引:索引是建立在表的一列或多个列上的辅助对象,目的是加快访问表中的数据;

Oracle存储索引的数据结构是B*树(平衡树),位图索引也是如此,只不过是叶子节点不同B*数索引;

索引由根节点、分支节点和叶子节点组成,上级索引块包含下级索引块的索引数据,叶节点包含索引数据和确定行实际位置的rowid。

2.索引建设原则

(1)索引应该经常建在Where 子句经常用到的列上。如果某个大表经常使用某个字段进行查询,并且检索行数小于总表行数的5%。则应该考虑。

(2)、对于两表连接的字段,应该建立索引。如果经常在某表的一个字段进行Order By 则也经过进行索引。

(3)、不应该在小表上建设索引。

3.索引分类

B树索引、位图索引、哈希索引

单列索引和复合索引

4.实验问题及实验内容

1)使用索引和不使用索引时候速度对比;

2)结合分区,分区和索引对比

3)位图索引的优势体现;

5.实验数据

使用的orders表(150万条数据),customer表(15万条数据)

6.小实验一(B树索引)

(1)建立索引sql

CREATE INDEX index_orderkey ON ORDERS('O_ORDERKEY');

(2)测试使用的sql语句

1.SELECT *FROM ORDERS WHERE O_TOTALPRICE>10000;

2.SELECT *FROM ORDERS WHERE O_ORDERDATE

between to_date('1994-01-01 00:00:00','yyyy-mm-dd hh24:mi:ss') 

and to_date('1995-12-31 00:00:00','yyyy-mm-dd hh24:mi:ss');

3.SELECT *FROM ORDERS WHERE O_ORDERKEY>100000 AND O_CUSTKEY<200000;

4.SELECT *FROM ORDERS WHERE O_ORDERSTATUS='O';

5.SELECT *FROM ORDERS WHERE O_CLERK LIKE 'Clerk#0000003%';

6.SELECT * FROM ORDERSBYTIME WHERE O_ORDERKEY>1000 AND O_ORDERKEY<20000;

 

(3)实验结果对比     时间:秒                    第一次和第二次的时间

Sql语句

不使用索引

使用B树索引(用orderkey字段作为索引)

 

没有建立分区表

建立hash分区表

没有建立分区表

建立hash分区表

SQL语句1

37.781

29.163

26.157

22.358

42.896s

24.980

30.309

23.292

SQL语句2

8.5000

8.001

10.408

8.039

7.370

7.776

7.662

8.127

SQL语句3

24.611

23.906

24.075

23.078

24.590

23.003

24.758

23.455

Sql语句4

11.673

13.214

11.354

11.298

12.333

11.395

12.123

10.964

Sql语句5

3.433

2.813

3.133

3.028

2.929

2.949

2.852

2.774

Sql语句6

0.281

0.306

0.415

0.340

0.339

0.261

0.389

0.309

(4)实验分析

没有得到显著的提高,索引不正确?数据量不够?只有细微的提高,感觉不正确。

换表重新测试使用LINEITEM     600万条数据

SELECT *FROM LINEITEM WHERE L_ORDERKEY>2513090;(第一次和第二次)

没有索引:158.972s                   119.364

有索引:  121.647s                   108.265

SELECT *FROM LINEITEM WHERE L_ORDERKEY=2513090;

没有索引:1.675s                       1.442

有索引:   0.039                      0.003

CREATE INDEX index_orderkey ON LINEITEM(L_ORDERKEY)

9.629s

可以看到,使用了索引之后速度提高很是明显。索引起作用了。至于之前的结果数据没有分析出原因。

7.实验二(位图索引)

1)使用使用LINEITEM   600万条数据

L_RETURNFLAG 这个字段只有:’N’,’A’,’R’

create index indexL1  on LINEITEM(L_RETURNFLAG);

create bitmap index indexL2  on LINEITEM(L_RETURNFLAG);

2)测试用sql语句

select *from LINEITEM where L_RETURNFLAG='N';

3)结果对比

Sql语句

没有索引

位图索引

B树索引

语句1

101.857

89.541

101.722

115.794

87.867

86.332

 

4)      结果分析

位图索引没有提高查询速度,B树索引有所提高,但不大。

8索引实验总结

两次实验得到的结果都不是令人满意,没有找到原因。第一次实验的改进实验得到了意料中的结果,符合所学的知识。

索引主要进行提高数据的查询速度。 当进行DML时,会更新索引。因此索引越多,则DML越慢,其需要维护索引。 因此在创建索引及DML需要权衡。

 

 

 

五.Oracle绑定变量与非绑定变量对比(实验三)

1.  绑定变量:oracle 中,对于一个提交的sql语句,存在两种可选的解析过程, 一种叫做硬解析,一种叫做软解析.

一个硬解析需要经解析,制定执行路径,优化访问计划等许多的步骤.硬解释不仅仅耗费大量的cpu,更重要的是会占据重要的们闩(latch)资源,严重的影响系统的规模的扩大(即限制了系统的并发行), 而且引起的问题不能通过增加内存条和cpu的数量来解决。

之所以这样是因为门闩是为了顺序访问以及修改一些内存区域而设置的,这些内存区域是不能被同时修改。当一个sql语句提交后,oracle会首先检查一下共享缓冲池(shared pool)里有没有与之完全相同的语句,如果有的话只须执行软分析即可,否则就得进行硬分析。

而唯一使得oracle 能够重复利用执行计划的方法就是采用绑定变量。绑定变量的实质就是用于替代sql语句中的常量的替代变量。绑定变量能够使得每次提交的sql语句都完全一样。

2.  实验问题以及实验内容

(1)  绑定变量与没有绑定变量时候查询速度差异对比

(2)  分析原因

3.  实验数据

(1) Orders表(150万条数据),备用表Lineitem(600万条数据)

4.  实验代码截图

(1) 没使用绑定变量截图

oracle分区表、索引、绑定变量等速度测试_第1张图片

(2)使用绑定变量截图

oracle分区表、索引、绑定变量等速度测试_第2张图片

(3)实验结果分析

使用绑定变量和没用绑定变量速度几乎一样,怀疑是12c自动使用了绑定变量。重新设计一个实验。

(4)新实验

分别使用绑定变量和不使用绑定变量分别向表中插入10000条数据,测量所使用的时间

  1.绑定变量的测试

oracle分区表、索引、绑定变量等速度测试_第3张图片

2.没有使用绑定变量的测试

oracle分区表、索引、绑定变量等速度测试_第4张图片

(5)新实验分析

还是没有显著的变化(只提高一倍?!),不知道,问题出在哪里。网上搜索寻找答案。

5.    实验总结

绑定变量是在通常情况下能提升效率,非正常的情况如下:

在字段(包括字段集)建有索引,且字段(集)的集的势非常大(也就是有个值在字段中出现的比例特别的大)的情况下,使用绑定变量可能会导致查询计划错误,因而会使查询效率非常低。这种情况最好不要使用绑定变量。

但是并不是任何情况下都需要使用绑定变量,下面是两种例外情况:

1.对于隔相当一段时间才执行一次的SQL语句,这是利用绑定变量的好处会被不能有效利用优化器而抵消

2.数据仓库的情况下。

绑定变量不能当作嵌入的字符串来使用,只能当作语句中的变量来用。不能用绑定变量来代替表名、过程名、字段名等.

从效率来看,由于oracle10G放弃了RBO,全面引入CBO,因此,在10G中使用绑定变量效率的提升比9i中更为明显。

 

 

 

 

 

 

 

你可能感兴趣的:(课程实验)