引言:这是我在学习谭老师SQL优化课程后的总结和实验,这里我主要通过sql_trace和10046事件来分析了sql资源消耗的情况,包含了 “结果集重用优化和分区索引优化”两部分,希望通过这些给一些初次涉及优化的DBA一些思路和启发。希望大家提出宝贵意见!

1.自己构造两条不同的SQL来完成相同的查询,注意结果集重用对SQL性能的影响

四个主人公:alan  leonarding  sun   xy

故事:这4个小伙伴刚刚毕业,毕业后都顺利的找到了工作,现在已经工作半年了,一次他们聚在了一起,由于虚荣心的驱动他们想比一比谁的工资攒的多,大家都是学IT出身,于是他们做了一个leo_salary表来计算他们这半年来的平均工资!

创建了leo_salary表,雇员id  名/字  薪水  月份

LS@LEO> create table leo_salary (employee_id number,name varchar(20),salary number,month date);

Table created.

LS@LEO> insert into leo_salary values (1,'alan',1000,to_date('2012_01_01','yyyy-mm-dd'));    alan同学工资

insert into leo_salary values (1,'alan',1100,to_date('2012_02_01','yyyy-mm-dd'));

insert into leo_salary values (1,'alan',1200,to_date('2012_03_01','yyyy-mm-dd'));

insert into leo_salary values (1,'alan',1300,to_date('2012_04_01','yyyy-mm-dd'));

insert into leo_salary values (1,'alan',1400,to_date('2012_05_01','yyyy-mm-dd'));

insert into leo_salary values (1,'alan',1500,to_date('2012_06_01','yyyy-mm-dd'));

insert into leo_salary values (2,'leonarding',200,to_date('2012_01_01','yyyy-mm-dd'));      leonarding同学工资

insert into leo_salary values (2,'leonarding',210,to_date('2012_02_01','yyyy-mm-dd'));

insert into leo_salary values (2,'leonarding',220,to_date('2012_03_01','yyyy-mm-dd'));

insert into leo_salary values (2,'leonarding',230,to_date('2012_04_01','yyyy-mm-dd'));

insert into leo_salary values (2,'leonarding',240,to_date('2012_05_01','yyyy-mm-dd'));

insert into leo_salary values (2,'leonarding',250,to_date('2012_06_01','yyyy-mm-dd'));

insert into leo_salary values (3,'sun',400,to_date('2012_01_01','yyyy-mm-dd'));            sun同学工资

insert into leo_salary values (3,'sun',410,to_date('2012_02_01','yyyy-mm-dd'));

insert into leo_salary values (3,'sun',420,to_date('2012_03_01','yyyy-mm-dd'));

insert into leo_salary values (3,'sun',430,to_date('2012_04_01','yyyy-mm-dd'));

insert into leo_salary values (3,'sun',440,to_date('2012_05_01','yyyy-mm-dd'));

insert into leo_salary values (3,'sun',450,to_date('2012_06_01','yyyy-mm-dd'));

insert into leo_salary values (4,'xy',600,to_date('2012_01_01','yyyy-mm-dd'));             xy同学工资

insert into leo_salary values (4,'xy',610,to_date('2012_02_01','yyyy-mm-dd'));

insert into leo_salary values (4,'xy',620,to_date('2012_03_01','yyyy-mm-dd'));

insert into leo_salary values (4,'xy',630,to_date('2012_04_01','yyyy-mm-dd'));

insert into leo_salary values (4,'xy',640,to_date('2012_05_01','yyyy-mm-dd'));

insert into leo_salary values (4,'xy',650,to_date('2012_06_01','yyyy-mm-dd'));

commit;

LS@LEO> select count(*) from leo_salary;

COUNT(*)

----------

24

LS@LEO> select * from leo_salary;

EMPLOYEE_ID NAME                     SALARY MONTH

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

1 alan                       1000 2012-01-01 00:00:00

1 alan                       1100 2012-02-01 00:00:00

1 alan                       1200 2012-03-01 00:00:00

1 alan                       1300 2012-04-01 00:00:00

1 alan                       1400 2012-05-01 00:00:00

1 alan                       1500 2012-06-01 00:00:00

2 leonarding                  200 2012-01-01 00:00:00

2 leonarding                  210 2012-02-01 00:00:00

2 leonarding                  220 2012-03-01 00:00:00

2 leonarding                  230 2012-04-01 00:00:00

2 leonarding                  240 2012-05-01 00:00:00

2 leonarding                  250 2012-06-01 00:00:00

3 sun                         400 2012-01-01 00:00:00

3 sun                         410 2012-02-01 00:00:00

3 sun                         420 2012-03-01 00:00:00

3 sun                         430 2012-04-01 00:00:00

3 sun                         440 2012-05-01 00:00:00

3 sun                         450 2012-06-01 00:00:00

4 xy                          600 2012-01-01 00:00:00

4 xy                          610 2012-02-01 00:00:00

4 xy                          620 2012-03-01 00:00:00

4 xy                          630 2012-04-01 00:00:00

4 xy                          640 2012-05-01 00:00:00

4 xy                          650 2012-06-01 00:00:00

24 rows selected.

LS@LEO> select name,avg(salary) avg_salary from leo_salary group by name;     这4个人平均工资

NAME                 AVG_SALARY

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

leonarding                  225

alan                       1250

xy                          625

sun                         425

他们又开始琢磨,想看看大家加在一起的平均基数是多少?

LS@LEO> select avg(avg_salary) from (select name,avg(salary) avg_salary from leo_salary group by name);

AVG(AVG_SALARY)

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

631.25    基数

于是alan提议,比一比谁的平均工资超过了基数?

set timing on   显示执行时间

LS@LEO> select * from (select name,avg(salary) avg_salary from leo_salary group by name) t where t.avg_salary > (select avg(avg_salary) from (select name,avg(salary) avg_salary from leo_salary group by name));

NAME                 AVG_SALARY

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

alan                       1250    只有一位选手出线

Elapsed: 00:00:00.02

很明显“select name,avg(salary) avg_salary from leo_salary group by name”子句已经被重复执行了,可以通过with子句,可以将该子句独立出来,并重用其查询结果!

LS@LEO> with name_avg_salary as (select name,avg(salary) avg_salary from leo_salary group by name)

select * from name_avg_salary t where t.avg_salary > (select avg(avg_salary) from name_avg_salary);

NAME                 AVG_SALARY

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

alan                       1250

Elapsed: 00:00:00.03

小结:我们把子句【with name_avg_salary as (select name,avg(salary) avg_salary from leo_salary group by name)】的结果作为临时变量存起来,在其后的查询中,可以直接使用name_avg_salary变量,如同name_avg_salary是一个真实存在的数据表一样。

下面我们用另一种写法来构造相同的查询,我没有重用原来的结果集,而是重新把所有工资加起来在整除

LS@LEO> select * from (select name,avg(salary) avg_salary from leo_salary group by name) t where t.avg_salary > (select sum(salary)/24 from leo_salary);

NAME                 AVG_SALARY

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

alan                       1250    也得到同样的结果,但比第一种耗时较长

Elapsed: 00:00:00.04

小结:我没有重用原来的结果集,而是重新把所有工资加起来在整除之后对比得出结论,这种方法显然没有第一种高效,会有更多的资源开销,这也体现出减少数据块的访问是SQL的优化之道!

注:由于我的样本数据较少,偶尔会出现两种sql耗时一样的情况,后面我会用sql_trace工具来详细分析sql性能指标)

“后来我们一致决定,让攒的最多alan同学请客Happy!”

我们用sql_trace工具测试一下上述2个sql资源消耗情况

LS@LEO> execute dbms_stats.gather_table_stats(ownname=>'LS',tabname=>'LEO_SALARY',method_opt=>'for all indexed columns size 2',cascade=>TRUE);                                                收集表leo_salary的统计信息

PL/SQL procedure successfully completed.

LS@LEO> alter session set tracefile_identifier='my_salary';       设置trace文件标识

LS@LEO> alter session set sql_trace=true;                         打开trace功能,追踪sql资源消耗情况

LS@LEO> select * from (select name,avg(salary) avg_salary from leo_salary group by name) t where t.avg_salary > (select avg(avg_salary) from (select name,avg(salary) avg_salary from leo_salary group by name));    重用结果集语句

NAME                 AVG_SALARY

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

alan                       1250

LS@LEO> select * from (select name,avg(salary) avg_salary from leo_salary group by name) t where t.avg_salary > (select sum(salary)/24 from leo_salary);                                                                         不重用结果集语句

NAME                 AVG_SALARY

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

alan                       1250

LS@LEO> alter session set sql_trace=false;

注:直接退出sqlplus工具也可以终止sql_trace功能

-rw-r-----  1 oracle oinstall    8955 Aug 26 20:41 leo_ora_20711_my_salary.trc

$ tkprof leo_ora_21094_my_salary.trc leo_my_salary.txt sys=no

-rw-r--r--  1 oracle oinstall    8389 Aug 26 20:45 leo_my_salary.trc

more leo_my_salary.txt

select * from (select name,avg(salary) avg_salary from leo_salary group by name) t where t.avg_salary > (select avg(avg_salary) from

(select name,avg(salary) avg_salary from leo_salary group by name))

call     count       cpu    elapsed       disk      query    current        rows

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

Parse        1      0.00       0.00          0          0          0           0

Execute      1      0.00       0.01          0          0          0           0

Fetch        2      0.00       0.00          0         14          0           1

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

total        4      0.00       0.01          0         14          0           1

Misses in library cache during parse: 0

Optimizer mode: ALL_ROWS

Parsing user id: 27

Rows     Row Source Operation

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

1  FILTER  (cr=29 pr=0 pw=0 time=5160 us)

4   HASH GROUP BY (cr=22 pr=0 pw=0 time=4819 us)

24    TABLE ACCESS FULL LEO_SALARY (cr=7 pr=0 pw=0 time=290 us)

1   SORT AGGREGATE (cr=7 pr=0 pw=0 time=320 us)

4    VIEW  (cr=7 pr=0 pw=0 time=286 us)

4     SORT GROUP BY (cr=7 pr=0 pw=0 time=234 us)

24      TABLE ACCESS FULL LEO_SALARY (cr=7 pr=0 pw=0 time=222 us)

********************************************************************************

select * from (select name,avg(salary) avg_salary from leo_salary group by name) t where t.avg_salary > (select sum(salary)/24 from leo_salary)

call     count       cpu    elapsed       disk      query    current        rows

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

Parse        1      0.00       0.00          0          0          0           0

Execute      1      0.00       0.03          0          0          0           0

Fetch        2      0.00       0.00          0         14          0           1

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

total        4      0.00       0.03          0         14          0           1

Misses in library cache during parse: 0

Optimizer mode: ALL_ROWS

Parsing user id: 27

Rows     Row Source Operation

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

1  FILTER  (cr=29 pr=0 pw=0 time=39433 us)

4   HASH GROUP BY (cr=22 pr=0 pw=0 time=39313 us)

24    TABLE ACCESS FULL LEO_SALARY (cr=7 pr=0 pw=0 time=238 us)

1   SORT AGGREGATE (cr=7 pr=0 pw=0 time=99 us)

24    TABLE ACCESS FULL LEO_SALARY (cr=7 pr=0 pw=0 time=218 us)

********************************************************************************

小结:从资源消耗的时间来看,结果集重用比不重用可以节约不少时间,所以说重用结果集可以提高我们的效率

10046事件分析sql执行性能

LS@LEO> alter session set events '10046 trace name context forever,level 12';    启动10046事件,执行了同样的两条sql

LS@LEO> select * from (select name,avg(salary) avg_salary from leo_salary group by name) t where t.avg_salary > (select avg(avg_salary) from (select name,avg(salary) avg_salary from leo_salary group by name));

NAME                 AVG_SALARY

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

alan                       1250

LS@LEO> select * from (select name,avg(salary) avg_salary from leo_salary group by name) t where t.avg_salary > (select sum(salary)/24 from leo_salary);

NAME                 AVG_SALARY

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

alan                       1250

LS@LEO> alter session set events '10046 trace name context off';                 关闭10046事件

-rw-r-----  1 oracle oinstall    7386 Aug 26 21:11 leo_ora_21593.trc

$ tkprof leo_ora_21593.trc leo_my_salary1.txt sys=no                             过滤trace文件

-rw-r--r--  1 oracle oinstall    8405 Aug 26 21:18 leo_my_salary1.txt

$ more leo_my_salary1.txt

select * from (select name,avg(salary) avg_salary from leo_salary group by name) t where t.avg_salary > (select avg(avg_salary) from (select name,avg(salary) avg_salary from leo_salary group by name))

call     count       cpu    elapsed       disk      query    current        rows

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

Parse        1      0.00       0.00          0          0          0           0

Execute      1      0.00       0.00          0          0          0           0

Fetch        2      0.00       0.01          0         14          0           1

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

total        4      0.00       0.01          0         14          0           1

Misses in library cache during parse: 0

Optimizer mode: ALL_ROWS

Parsing user id: 27

Rows     Row Source Operation

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

1  FILTER  (cr=29 pr=0 pw=0 time=14532 us)

4   HASH GROUP BY (cr=22 pr=0 pw=0 time=14089 us)

24    TABLE ACCESS FULL LEO_SALARY (cr=7 pr=0 pw=0 time=11004 us)

1   SORT AGGREGATE (cr=7 pr=0 pw=0 time=406 us)

4    VIEW  (cr=7 pr=0 pw=0 time=289 us)

4     SORT GROUP BY (cr=7 pr=0 pw=0 time=228 us)

24      TABLE ACCESS FULL LEO_SALARY (cr=7 pr=0 pw=0 time=279 us)

Elapsed times include waiting on following events:                                  等待事件

Event waited on                             Times   Max. Wait  Total Waited

----------------------------------------   Waited  ----------  ------------

SQL*Net message to client                       2        0.00          0.00

SQL*Net message from client                     2        0.00          0.00

********************************************************************************

select * from (select name,avg(salary) avg_salary from leo_salary group by name) t where t.avg_salary > (select sum(salary)/24 from leo_salary)

call     count       cpu    elapsed       disk      query    current        rows

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

Parse        1      0.00       0.00          0          0          0           0

Execute      1      0.00       0.01          0          0          0           0

Fetch        2      0.00       0.00          0         14          0           1

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

total        4      0.00       0.01          0         14          0           1

Misses in library cache during parse: 0

Optimizer mode: ALL_ROWS

Parsing user id: 27

Rows     Row Source Operation

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

1  FILTER  (cr=29 pr=0 pw=0 time=15467 us)

4   HASH GROUP BY (cr=22 pr=0 pw=0 time=15240 us)

24    TABLE ACCESS FULL LEO_SALARY (cr=7 pr=0 pw=0 time=322 us)

1   SORT AGGREGATE (cr=7 pr=0 pw=0 time=193 us)

24    TABLE ACCESS FULL LEO_SALARY (cr=7 pr=0 pw=0 time=265 us)

Elapsed times include waiting on following events:                                  等待事件

Event waited on                             Times   Max. Wait  Total Waited

----------------------------------------   Waited  ----------  ------------

SQL*Net message to client                       2        0.00          0.00

SQL*Net message from client                     2        0.00          0.00

********************************************************************************

小结:从资源消耗的时间来看,第一个sql还是比第二个sql效率高些!

2.对于分区表, 当查询范围在一个分区以内以及跨分区查询时,比较本地索引和全局索引的性能差异。

创建一个分区表 leo_my_partition1

LS@LEO> create table leo_my_partition1

partition by range (object_id)

(

partition leo_p1 values less than (1000),

partition leo_p2 values less than (2000),

partition leo_p3 values less than (3000),

partition leo_p4 values less than (4000),

partition leo_p5 values less than (5000),

partition leo_max values less than (maxvalue)

)

as select *  from dba_objects;

前5个分区的记录数基本上分布的比较均匀

LS@LEO> select count(*) from leo_my_partition1 partition (leo_p1);      leo_p1分区有953条记录

COUNT(*)

----------

953

LS@LEO> select count(*) from leo_my_partition1 partition (leo_p2);      leo_p2分区有1000条记录

COUNT(*)

----------

1000

LS@LEO> select count(*) from leo_my_partition1 partition (leo_p3);      leo_p3分区有1000条记录

COUNT(*)

----------

1000

LS@LEO> select count(*) from leo_my_partition1 partition (leo_p4);      leo_p4分区有988条记录

COUNT(*)

----------

988

LS@LEO> select count(*) from leo_my_partition1 partition (leo_p5);      leo_p5分区有975条记录

COUNT(*)

----------

975

LS@LEO> select count(*) from leo_my_partition1 partition (leo_max);     leo_max分区有5448条记录

COUNT(*)

----------

5448

下面增加些赠送的小知识和需要记住的话,并不是我实际操作的

本地索引-有几个分区就有几个索引

create index  leo_my_partition1_index_local on leo_my_partition1(object_id) local;        别忘了关键字“local”哦

解释:

1.这是本地索引,每个分区一个索引,有几个分区就有几个索引,要么所有分区都建本地索引,要么所有分区都不建本地索引

2.truncate  delete  update  insert  都不会影响本地索引

3.如果不指定具体分区索引名那么系统会自动起名字

全局索引-一个分区表只能有一个全局索引

create index  leo_my_partition1_index_local on leo_my_partition1(object_id);          这是全局索引

解释:

1.增加和删除分区会导致全局索引失效

2.truncate 操作会导致全局索引失效

3.delete 操作不会导致全局索引失效

4.使用“update global indexes”选项实现truncate分区时保证全局索引有效

LS@LEO> alter table leo_my_partition1 truncate partition leo_p1 update global indexes;

下面我要创建的是自己命名的本地分区索引

LS@LEO> create index leo_my_partition1_index_local on leo_my_partition1(object_id)

local

(

partition leo_my_partition1_index_local_1 ,

partition leo_my_partition1_index_local_2 ,

partition leo_my_partition1_index_local_3 ,

partition leo_my_partition1_index_local_4 ,

partition leo_my_partition1_index_local_5 ,

partition leo_my_partition1_index_local_max

);

2    3    4    5    6    7    8    9   10      partition leo_my_partition1_index_local_1 ,

*

ERROR at line 4:

ORA-00972: identifier is too long

报错,真奇怪,查询一下

$ oerr ora 972      格式:oerr  错误类型  错误代码

00972, 00000, "identifier is too long"

// *Cause:  An identifier with more than 30 characters was specified.

// *Action:  Specify at most 30 characters.

ORA-00972 identifier is too long

Cause: The name of a schema object exceeds 30 characters. Schema objects are

tables, clusters, views, indexes, synonyms, tablespaces, and usernames.

Action: Shorten the name to 30 characters or less.

原因:模式对象名不能超过30个字符,解决把名字长度减少,例如表名 视图名 索引名 同义词 表空间啊 名称的长度都不能超过30个字符哦

LS@LEO> create index leo_my_partition1_index_local on leo_my_partition1(object_id)   本地分区索引创建成功

local

(

partition local_index_1 ,

partition local_index_2 ,

partition local_index_3 ,

partition local_index_4 ,

partition local_index_5 ,

partition local_index_max

);

Index created.

检查本地分区索引是否有效

LS@LEO> select index_name,status,tablespace_name,partitioned from dba_indexes where table_name in ('LEO_MY_PARTITION1');

INDEX_NAME                     STATUS   TABLESPACE_NAME                PAR

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

LEO_MY_PARTITION1_INDEX_LOCAL  N/A                                     YES

创建另一个分区表leo_my_partition2

LS@LEO> create table leo_my_partition2

partition by range (object_id)

(

partition leo_p1 values less than (1000),

partition leo_p2 values less than (2000),

partition leo_p3 values less than (3000),

partition leo_p4 values less than (4000),

partition leo_p5 values less than (5000),

partition leo_max values less than (maxvalue)

)

as select *  from dba_objects;

每个分区的记录数和partition1差不多

LS@LEO> select count(*) from leo_my_partition2 partition (leo_p1);

select count(*) from leo_my_partition2 partition (leo_p2);

select count(*) from leo_my_partition2 partition (leo_p3);

select count(*) from leo_my_partition2 partition (leo_p4);

select count(*) from leo_my_partition2 partition (leo_p5);

select count(*) from leo_my_partition2 partition (leo_max);

COUNT(*)

----------

953

LS@LEO>

COUNT(*)

----------

1000

LS@LEO>

COUNT(*)

----------

1000

LS@LEO>

COUNT(*)

----------

988

LS@LEO>

COUNT(*)

----------

975

LS@LEO>

COUNT(*)

----------

5462

LS@LEO>

我们给partition2表创建全局分区索引

LS@LEO> create index global_index_1  on leo_my_partition2(object_id);     创建成功

Index created.

检查全局分区索引是否有效

LS@LEO> select index_name,status,tablespace_name,partitioned from dba_indexes where table_name in ('LEO_MY_PARTITION2');

INDEX_NAME                     STATUS   TABLESPACE_NAME                PAR

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

GLOBAL_INDEX_1                 VALID    USERS                          NO

收集2张表的统计信息

LS@LEO> execute dbms_stats.gather_table_stats(ownname=>'LS',tabname=>'LEO_MY_PARTITION1',method_opt=>'for all indexed columns size 2',cascade=>TRUE);

PL/SQL procedure successfully completed.

LS@LEO> execute dbms_stats.gather_table_stats(ownname=>'LS',tabname=>'LEO_MY_PARTITION2',method_opt=>'for all indexed columns size 2',cascade=>TRUE);

PL/SQL procedure successfully completed.

LS@LEO> alter session set tracefile_identifier='my_partition';    设置trace文件标识

LS@LEO> alter session set sql_trace=true;                         打开trace功能,追踪sql资源消耗情况

当查询范围在一个分区以内,本地索引和全局索引的性能比较

LS@LEO> select object_type,count(*) from leo_my_partition1 where object_id<900 group by object_type;     符合条件的对象类型的分类

OBJECT_TYPE           COUNT(*)

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

SEQUENCE                    25

LOB                               44

PACKAGE                       4

PACKAGE BODY             2

TABLE                            318

INDEX                            376

SYNONYM                      6

CLUSTER                      10

TYPE                             68

9 rows selected.

LS@LEO> select object_type,count(*) from leo_my_partition2 where object_id<900 group by object_type;     符合条件的对象类型的分类

OBJECT_TYPE           COUNT(*)

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

SEQUENCE                   25

LOB                              44

PACKAGE                      4

PACKAGE BODY            2

TABLE                          318

INDEX                          376

SYNONYM                    6

CLUSTER                    10

TYPE                           68

9 rows selected.

当查询范围跨分区时,本地索引和全局索引的性能比较

LS@LEO> select object_type,count(*) from leo_my_partition1 where object_id<5000 group by object_type;

OBJECT_TYPE           COUNT(*)

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

CONSUMER GROUP               4

SEQUENCE                            40

QUEUE                                  8

PROCEDURE                        14

LOB                                      67

PACKAGE                             124

PACKAGE BODY                   102

LIBRARY                              35

TYPE BODY                         11

TRIGGER                             1

TABLE                                 429

INDEX                                498

SYNONYM                          1481

VIEW                                 1888

FUNCTION                          5

CLUSTER                           10

TYPE                                 196

RESOURCE PLAN                3

18 rows selected.

LS@LEO> select object_type,count(*) from leo_my_partition2 where object_id<5000 group by object_type;

OBJECT_TYPE           COUNT(*)

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

CONSUMER GROUP             4

SEQUENCE                         40

QUEUE                               8

PROCEDURE                     14

LOB                                   67

PACKAGE                          124

PACKAGE BODY               102

LIBRARY                           35

TYPE BODY                      11

TRIGGER                          1

TABLE                              429

INDEX                              498

SYNONYM                        1481

VIEW                               1888

FUNCTION                       5

CLUSTER                         10

TYPE                               196

RESOURCE PLAN             3

18 rows selected.

LS@LEO> alter session set sql_trace=false;        关闭trace功能

注:直接退出sqlplus工具也可以终止sql_trace功能

-rw-r-----  1 oracle oinstall   13492 Aug 26 12:57 leo_ora_10271_my_partition.trc   这就是我们输出的trace文件

tkprof工具的介绍

答:tkprof工具是用来过滤和汇总trace文件的,因为原始trace文件可读性是比较差,里面有许多跟我们诊断sql语句关系不太大的信息,所以我们需要使用tkprof工具来规范trace文件的格式,使过滤出来的文件更具有可读性!

使用tkprof工具来生成我们需要的SQL分析文件

格式:tkprof  trace文件   过滤后文件  参数

$ tkprof leo_ora_10271_my_partition.trc leo_test.txt sys=no   【sys=no  不输出sys用户运行sql语句,默认是yes,实际上设置成no更具有可读性】

TKPROF: Release 10.2.0.1.0 - Production on Sun Aug 26 19:05:34 2012

Copyright (c) 1982, 2005, Oracle.  All rights reserved.

-rw-r--r--  1 oracle oinstall   10060 Aug 26 19:05 leo_test.txt

tkprof 帮助文件,在命令行下直接敲入tkprof回车,就会显示出来

$ tkprof

Usage: tkprof tracefile outputfile [explain= ] [table= ]

[print= ] [insert= ] [sys= ] [sort= ]

table=schema.tablename   Use 'schema.tablename' with 'explain=' option.

explain=user/password    Connect to ORACLE and issue EXPLAIN PLAN.

print=integer    List only the first 'integer' SQL statements.

aggregate=yes|no

insert=filename  List SQL statements and data inside INSERT statements.

sys=no           TKPROF does not list SQL statements run as user SYS.

record=filename  Record non-recursive statements found in the trace file.

waits=yes|no     Record summary for any wait events found in the trace file.

sort=option      Set of zero or more of the following sort options:

prscnt  number of times parse was called

prscpu  cpu time parsing

prsela  elapsed time parsing

prsdsk  number of disk reads during parse

prsqry  number of buffers for consistent read during parse

prscu   number of buffers for current read during parse

prsmis  number of misses in library cache during parse

execnt  number of execute was called

execpu  cpu time spent executing

exeela  elapsed time executing

exedsk  number of disk reads during execute

exeqry  number of buffers for consistent read during execute

execu   number of buffers for current read during execute

exerow  number of rows processed during execute

exemis  number of library cache misses during execute

fchcnt  number of times fetch was called

fchcpu  cpu time spent fetching

fchela  elapsed time fetching

fchdsk  number of disk reads during fetch

fchqry  number of buffers for consistent read during fetch

fchcu   number of buffers for current read during fetch

fchrow  number of rows fetched

userid  userid of user that parsed the cursor

$ more leo_test.txt

TKPROF: Release 10.2.0.1.0 - Production on Sun Aug 26 19:05:34 2012                  版本信息

Copyright (c) 1982, 2005, Oracle.  All rights reserved.

Trace file: leo_ora_10271_my_partition.trc                                           trace文件名字

Sort options: default

********************************************************************************

count    = number of times OCI procedure was executed                                当前操作被执行了多少次

cpu      = cpu time in seconds executing                                             cpu执行时间

elapsed  = elapsed time in seconds executing                                         整个执行时间

disk     = number of physical reads of buffers from disk                             磁盘物理读

query    = number of buffers gotten for consistent read                              一致性读(逻辑读,通常查询使用的方式)

current  = number of buffers gotten in current mode (usually for update)             当update时操作数据块

rows     = number of rows processed by the fetch or execute call                     处理的记录数

********************************************************************************

当查询范围在一个分区以内,本地索引和全局索引的性能比较

select object_type,count(*) from leo_my_partition1 where object_id<900 group by object_type

call     count       cpu    elapsed       disk      query    current        rows

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

Parse        1      0.00       0.01          0          0          0           0                1次硬解析

Execute      1      0.00       0.00          0          0          0           0                1次执行

Fetch        2      0.00       0.00          0         15          0           9                2次取操作

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

total        4      0.00       0.02          0         15          0           9

Misses in library cache during parse: 1

Optimizer mode: ALL_ROWS                           优化器模式ALL_ROWS:所有数据全部处理完后返回结果

Parsing user id: 27

Rows     Row Source Operation   行源操作

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

9  HASH GROUP BY (cr=30 pr=0 pw=0 time=6130 us)

853   PARTITION RANGE SINGLE PARTITION: 1 1 (cr=15 pr=0 pw=0 time=47987 us)                 关注消耗的时间

853    TABLE ACCESS FULL LEO_MY_PARTITION1 PARTITION: 1 1 (cr=15 pr=0 pw=0 time=7737 us)

********************************************************************************

select object_type,count(*) from leo_my_partition2 where object_id<900 group by object_type

call     count       cpu    elapsed       disk      query    current        rows

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

Parse        1      0.00       0.01          0          0          0           0               1次硬解析

Execute      1      0.00       0.01          0          0          0           0               1次执行

Fetch        2      0.00       0.00          0         15          0           9               2次取操作

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

total        4      0.00       0.03          0         15          0           9

Misses in library cache during parse: 1

Optimizer mode: ALL_ROWS                           优化器模式ALL_ROWS:所有数据全部处理完后返回结果

Parsing user id: 27

Rows     Row Source Operation   行源操作

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

9  HASH GROUP BY (cr=30 pr=0 pw=0 time=21773 us)

853   PARTITION RANGE SINGLE PARTITION: 1 1 (cr=15 pr=0 pw=0 time=13817 us)               关注消耗的时间

853    TABLE ACCESS FULL LEO_MY_PARTITION2 PARTITION: 1 1 (cr=15 pr=0 pw=0 time=5271 us)

********************************************************************************

小结:执行计划走的是全表扫描(只扫描了第一个分区),CBO认为全表扫描性能最优,但我们从消耗的时间来看leo_my_partition1比leo_my_partition2花的时间长,leo_my_partition2性能更优!

select object_type,count(*) from leo_my_partition1 where object_id<5000 group by object_type

call     count       cpu    elapsed       disk      query    current        rows

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

Parse        1      0.00       0.01          0          0          0           0              1次硬解析

Execute      1      0.00       0.00          0          0          0           0              1次执行

Fetch        3      0.00       0.01          0         78          0          18              3次取操作

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

total        5      0.01       0.03          0         78          0          18

Misses in library cache during parse: 1

Optimizer mode: ALL_ROWS                           优化器模式ALL_ROWS:所有数据全部处理完后返回结果

Parsing user id: 27

Rows     Row Source Operation   行源操作

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

18  HASH GROUP BY (cr=93 pr=0 pw=0 time=16643 us)

4916   PARTITION RANGE ITERATOR PARTITION: 1 5 (cr=78 pr=0 pw=0 time=123072 us)

4916    TABLE ACCESS FULL LEO_MY_PARTITION1 PARTITION: 1 5 (cr=78 pr=0 pw=0 time=41851 us)

********************************************************************************

select object_type,count(*) from leo_my_partition2 where object_id<5000 group by object_type

call     count       cpu    elapsed       disk      query    current        rows

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

Parse        1      0.00       0.01          0          0          0           0               1次硬解析

Execute      1      0.00       0.00          0          0          0           0               1次执行

Fetch        3      0.00       0.01          0         78          0          18               3次取操作

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

total        5      0.01       0.03          0         78          0          18

Misses in library cache during parse: 1

Optimizer mode: ALL_ROWS                            优化器模式ALL_ROWS:所有数据全部处理完后返回结果

Parsing user id: 27

Rows     Row Source Operation   行源操作

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

18  HASH GROUP BY (cr=93 pr=0 pw=0 time=16707 us)

4916   PARTITION RANGE ITERATOR PARTITION: 1 5 (cr=78 pr=0 pw=0 time=1007722 us)

4916    TABLE ACCESS FULL LEO_MY_PARTITION2 PARTITION: 1 5 (cr=78 pr=0 pw=0 time=69092 us)

********************************************************************************

小结:执行计划走的是全表扫描(扫描了1-5分区),CBO认为全表扫描性能最优,但我们从消耗的时间来看leo_my_partition1比leo_my_partition2花的时间少,leo_my_partition1性能更优!

10046事件分析sql执行性能

解释:10046事件是发生在sql的执行过程中,它能够全面分析出sql执行过程和所消耗的资源,让你了解这条sql是否是最优的,10046事件有4个级别

LEVEL  1   等同于SQL_TRACE的功能

LEVEL  4   在LEVEL 1基础上增加绑定变量信息

LEVEL  8   在LEVEL 1基础上增加等待事件信息

LEVEL  12  等同于LEVEL  4+LEVEL  8,即有绑定变量信息又有等待事件信息

我们再次收集一下表统计信息

LS@LEO> execute dbms_stats.gather_table_stats(ownname=>'LS',tabname=>'LEO_MY_PARTITION1',method_opt=>'for all indexed columns size 2',cascade=>TRUE);

PL/SQL procedure successfully completed.

LS@LEO> execute dbms_stats.gather_table_stats(ownname=>'LS',tabname=>'LEO_MY_PARTITION2',method_opt=>'for all indexed columns size 2',cascade=>TRUE);

PL/SQL procedure successfully completed.

LS@LEO> alter session set events '10046 trace name context forever,level 12';   启动10046事件,执行了同样的四条sql

select object_type,count(*) from leo_my_partition1 where object_id<900 group by object_type;

select object_type,count(*) from leo_my_partition2 where object_id<900 group by object_type;

select object_type,count(*) from leo_my_partition1 where object_id<5000 group by object_type;

select object_type,count(*) from leo_my_partition2 where object_id<5000 group by object_type;

LS@LEO> alter session set events '10046 trace name context off';                关闭10046事件

$ tkprof leo_ora_19950.trc leo_test1.txt sys=no                                 过滤trace文件

TKPROF: Release 10.2.0.1.0 - Production on Sun Aug 26 20:11:44 2012

Copyright (c) 1982, 2005, Oracle.  All rights reserved.

$ more leo_test1.txt

select object_type,count(*) from leo_my_partition1 where object_id<900 group by object_type

call     count       cpu    elapsed       disk      query    current        rows

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

Parse        1      0.00       0.00          0          0          0           0

Execute      1      0.00       0.00          0          0          0           0

Fetch        2      0.00       0.00          0         15          0           9

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

total        4      0.00       0.00          0         15          0           9

Misses in library cache during parse: 0

Optimizer mode: ALL_ROWS

Parsing user id: 27

Rows     Row Source Operation

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

9  HASH GROUP BY (cr=30 pr=0 pw=0 time=6073 us)

853   PARTITION RANGE SINGLE PARTITION: 1 1 (cr=15 pr=0 pw=0 time=79555 us)

853    TABLE ACCESS FULL LEO_MY_PARTITION1 PARTITION: 1 1 (cr=15 pr=0 pw=0 time=11261 us)

Elapsed times include waiting on following events:

Event waited on                             Times   Max. Wait  Total Waited

----------------------------------------   Waited  ----------  ------------

SQL*Net message to client                       2        0.00          0.00         客户端等待服务器响应

SQL*Net message from client                     2        0.04          0.05         服务器等待客户端请求

********************************************************************************

select object_type,count(*) from leo_my_partition2 where object_id<900 group by object_type

call     count       cpu    elapsed       disk      query    current        rows

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

Parse        1      0.00       0.00          0          0          0           0

Execute      1      0.00       0.00          0          0          0           0

Fetch        2      0.00       0.00          0         15          0           9

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

total        4      0.00       0.00          0         15          0           9

Misses in library cache during parse: 0

Optimizer mode: ALL_ROWS

Parsing user id: 27

Rows     Row Source Operation

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

9  HASH GROUP BY (cr=30 pr=0 pw=0 time=4112 us)

853   PARTITION RANGE SINGLE PARTITION: 1 1 (cr=15 pr=0 pw=0 time=15652 us)

853    TABLE ACCESS FULL LEO_MY_PARTITION2 PARTITION: 1 1 (cr=15 pr=0 pw=0 time=4537 us)

Elapsed times include waiting on following events:

Event waited on                             Times   Max. Wait  Total Waited

----------------------------------------   Waited  ----------  ------------

SQL*Net message to client                       2        0.00          0.00

SQL*Net message from client                     2        0.00          0.00

********************************************************************************

小结:这次也是走的全表扫描,似乎leo_my_partition1比leo_my_partition2花的时间长,leo_my_partition12性能更优!10046事件比SQL_TRACE多了一项等待事件

select object_type,count(*) from leo_my_partition1 where object_id<5000 group by object_type

call     count       cpu    elapsed       disk      query    current        rows

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

Parse        1      0.00       0.00          0          0          0           0

Execute      1      0.00       0.00          0          0          0           0

Fetch        3      0.00       0.01          0         78          0          18

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

total        5      0.00       0.01          0         78          0          18

Misses in library cache during parse: 0

Optimizer mode: ALL_ROWS

Parsing user id: 27

Rows     Row Source Operation

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

18  HASH GROUP BY (cr=93 pr=0 pw=0 time=17019 us)

4916   PARTITION RANGE ITERATOR PARTITION: 1 5 (cr=78 pr=0 pw=0 time=83714 us)

4916    TABLE ACCESS FULL LEO_MY_PARTITION1 PARTITION: 1 5 (cr=78 pr=0 pw=0 time=25027 us)

Elapsed times include waiting on following events:

Event waited on                             Times   Max. Wait  Total Waited

----------------------------------------   Waited  ----------  ------------

SQL*Net message to client                       3        0.00          0.00         客户端等待服务器响应

SQL*Net message from client                     3        0.01          0.01         服务器等待客户端请求

********************************************************************************

select object_type,count(*) from leo_my_partition2 where object_id<5000 group by object_type

call     count       cpu    elapsed       disk      query    current        rows

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

Parse        1      0.00       0.00          0          0          0           0

Execute      1      0.00       0.00          0          0          0           0

Fetch        3      0.00       0.00          0         78          0          18

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

total        5      0.00       0.00          0         78          0          18

Misses in library cache during parse: 0

Optimizer mode: ALL_ROWS

Parsing user id: 27

Rows     Row Source Operation

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

18  HASH GROUP BY (cr=93 pr=0 pw=0 time=6602 us)

4916   PARTITION RANGE ITERATOR PARTITION: 1 5 (cr=78 pr=0 pw=0 time=78720 us)

4916    TABLE ACCESS FULL LEO_MY_PARTITION2 PARTITION: 1 5 (cr=78 pr=0 pw=0 time=29760 us)

Elapsed times include waiting on following events:

Event waited on                             Times   Max. Wait  Total Waited

----------------------------------------   Waited  ----------  ------------

SQL*Net message to client                       3        0.00          0.00

SQL*Net message from client                     3        0.01          0.01

********************************************************************************

小结:这次也是走的全表扫描,似乎leo_my_partition1比leo_my_partition2花的时间长,leo_my_partition12性能更优!10046事件比SQL_TRACE多了一项等待事件!

Leonarding

2012.8.26

天津&autumn

分享技术~收获快乐

Blog:http://space.itpub.net/26686207

oracle分区索引优化,SQL优化思路结果集重用优化、分区索引优化测试相关推荐

  1. 【数据操作】优化SQL server性能 之 索引 (转上)

    数据库的逻辑设计.包括表与表之间的关系是优化关系型数据库性能的核心.一个好的逻辑数据库设计可以为优化数据库和应用程序打下良好的基础. 数据库的逻辑设计.包括表与表之间的关系是优化关系型数据库性能的核心 ...

  2. 五十种巧妙优化SQL Server数据库

    五十种巧妙优化SQL Server数据库的方法:出现性能问题的原因- 没有索引或者没有用到索引(这是查询慢最常见的问题,是程序设计的缺陷). I/O吞吐量小,形成了瓶颈效应. 没有创建计算列导致查询不 ...

  3. 优化SQL Server的内存占用之执行缓存

    优化SQL Server的内存占用之执行缓存篇 优化SQL Server的内存占用之执行缓存 在论坛上常见有朋友抱怨,说SQL Server太吃内存了.这里笔者根据经验简单介绍一下内存相关的调优知识. ...

  4. Oracle 9i与MS SQL Server 2000之比较连载五.zz

    http://kb.cnblogs.com/a/1153156 Oracle 9i与MS SQL Server 2000之比较连载五 2008-04-14 18:13 四.Oracle中新的数据库对象 ...

  5. Oracle 建立索引及利用索引的SQL语句优化

    数据库索引: 索引有单列索引 复合索引之说 如何某表的某个字段有主键约束和唯一性约束,则Oracle 则会自动在相应的约束列上建议唯一索引.数据库索引主要进行提高访问速度. 建设原则: 1.索引应该经 ...

  6. oracle数据库创建索引以及简单优化sql语句

    Oracle 建立索引及SQL优化 数据库索引: 索引有单列索引 复合索引之说 如何某表的某个字段有主键约束和唯一性约束,则Oracle 则会自动在相应的约束列上建议唯一索引.数据库索引主要进行提高访 ...

  7. 创建索引oracle 很慢,Oracle 建立索引及SQL优化

    复合索引用户可以在多个列上建立索引,这种索引叫做复合索引(组合索引).复合索引的创建方法与创建单一索引的方法完全一样.但复合索引在数据库操作期间所需的开销更小,可以代替多个单一索引. 如何某表的某个字 ...

  8. 聊聊SQL优化的基础思路

    点击上方"蓝字" 关注我们,享更多干货! SQL优化是Oracle数据库中比较难的部分,需要对Oracle数据库具备非常扎实的理论基础.但是在刚开始接触时,往往不能很好地将理论知识 ...

  9. 基于索引的SQL语句优化之降龙十八掌

    一篇挺不错的关于SQL语句优化的文章,因不知原始出处,故未作引用说明! 1 前言       客服业务受到SQL语句的影响非常大,在规模比较大的局点,往往因为一个小的SQL语句不够优化,导致数据库性能 ...

  10. 基于索引的SQL语句优化之降龙十八掌(转载)!

    一篇挺不错的关于SQL语句优化的文章,因不知原始出处,故未作引用说明,如有侵权,请联系本人! 1 前言       客服业务受到SQL语句的影响非常大,在规模比较大的局点,往往因为一个小的SQL语句不 ...

最新文章

  1. python kafka offset自动提交_Spring-Kafka —— 实现批量消费和手动提交offset
  2. Linux SPI总线和设备驱动架构之二:SPI通用接口层
  3. asp.net,关于Listview+DataPager控件使用
  4. 计算机保护地阻值,机房接地系统的一般接地电阻要小于多少欧姆?
  5. 大数组,找某数字的左,右边界
  6. (全角→半角)把文字从PDF复制到Word,发现很宽但又不是多出空格?
  7. java简历自我评价_java程序员简历自我评价怎么写
  8. ns3安装 + eclipse
  9. 利用电力声类比与有限元仿真方法分析亥姆霍兹共振器
  10. 传统车载网络,软件定义汽车
  11. Modelica技术特点及优势
  12. Spring自定义消息转换器替换ResponseBody
  13. 斯坦福大学公开课:机器学习的动机与应用
  14. 计算机分辨率无法调整,电脑分辨率调不了怎么办?电脑分辨率不能调的解决方法...
  15. 2018年4月5日腾讯考试感想
  16. oracle的switch+case语句吗,2.7 switch 语句中的 case 范围
  17. Qt 之 QDateEdit 和 QTimeEdit
  18. Nvidia Xavier Nx平台GMSL接口imx390相机驱动调试记录
  19. 应用ceph块存储(ceph-13.2.10)
  20. STM32外围电路硬件解析

热门文章

  1. shell,expect主机密钥免密码登录分发
  2. 1.Kong入门与实战 基于Nginx和OpenResty的云原生微服务网关 --- 基础知识点概述
  3. Linux下安装jdk报Permission denied以及chmod详解
  4. [洛谷P4183][USACO18JAN]Cow at Large P
  5. UDF函数 解码url
  6. Vue项目使用AES做加密
  7. android中的适配器模式
  8. 5.2.8.字符设备驱动代码实践1
  9. aspx中如何加入javascript
  10. Linux dirname、basename 指令