Oracle中下一个SQL语句的优化过程(更详细)
选择和(sl0000)从xstfxps2哪里
dhao00在(
选择xstfxps1 TRUNC dhao00(ywrq00)= trunc(SYSDATE)
和khdm00 = '500000003913);
所用时间:00:02:49.04
U3000 U3000
执行计划
----------------------------------------------------------
0选择语句优化器=选择
10类(合计)
21嵌套循环
32访问表(全)of'xstfxps2
42表的访问(通过索引rowid)of'xstfxps1
54指数(独特的扫描)of'xstfxps1_pk(独特的)
U3000 U3000
统计
----------------------------------------------------------
0递归调用
0分贝块得到
17355138一致的获取
34141物理读
2912重做日志大小
198个字节通过网络发送给客户机
从客户端接收的275个字节
2 SQL*Net切换到/从客户端
0类(内存)
0类(磁盘)
1行处理
我们在数据上看到17355138个逻辑的读数,34141物理IO,这是相当可怕的数字。在执行计划中,我们看到桌上xstfxps2为全表扫描。
让我们看一下这两个表的总数据量。
SQL select count(*)>从xstfxps2;
U3000 U3000
计数(*)
----------
五百五十八万五千零一十八
我们在这里看到的,xstfxps2有记录5585018。
SQL select count(*)>从xstfxps1;
U3000 U3000
计数(*)
----------
七十万二千一百二十一
这两个表的表结构如下所示:
SQL> DESC xstfxps1
名称类型可为空的默认评论
-----------------------------------------
dhao00号(8)
lhdh00号码(8)Y
fldh00号码(8)Y
fplb00 VARCHAR2(2)Y
ywrq00日期
ywry00 VARCHAR2(8)Y
shrq00日期
xsqrrq日期
xsqrry VARCHAR2(8)Y
khdm00 VARCHAR2(12)
xkzh00 VARCHAR2(12)
ckdm00 VARCHAR2(2)Y
thckdm VARCHAR2(2)Y
xsfsdm VARCHAR2(2)Y
fxrydm VARCHAR2(4)Y
shrydm VARCHAR2(4)Y
shbj00 VARCHAR2(1)n
fxbj00 VARCHAR2(1)n
skbj00 VARCHAR2(2)Y
fkdm00 VARCHAR2(2)Y
U3000 U3000
SQL> DESC xstfxps2
名称类型可为空的默认评论
-----------------------------------------
dhao00号(8)
spdm00 VARCHAR2(8)
djia00数(7,2)0
fxsl00编号0
sl0000编号0
thsl00编号0
je0000编号0
se0000数Y
fpbbh0 VARCHAR2(11)Y
fphao0 VARCHAR2(10)Y
rbdh00号码(8)Y
U3000 U3000
的xstfxps1的客户订单,订单的客户信息、订单日期等on.xstfxps2是桌体的订单,客户订单的详细记录,商品的价格和数量信息。
U3000 U3000
第一步是调整查询提取,看语句的执行计划。一般来说,如果一个语句可以避免使用子查询,子查询是尽可能不使用。因为子查询的开销非常昂贵,重写声明如下:
选择和(sl0000)
从xstfxps2,(选择dhao00从xstfxps1 TRUNC(ywrq00)= trunc(SYSDATE)
和khdm00 = '500000003913)B
在a.dhao00 = b.dhao00;
所用时间:00:00:3.05
执行计划
----------------------------------------------------------
0选择语句优化器=选择
10类(合计)
21表的访问(通过索引rowid)of'xstfxps2
32嵌套循环
43访问表(全)of'xstfxps1
53指数(范围扫描)of'xstfxps2_pk(独特的)
统计
----------------------------------------------------------
0递归调用
0分贝块得到
11974一致的获取
225物理读
832重做日志大小
211个字节通过网络发送给客户机
从客户端接收的275个字节
2 SQL*Net切换到/从客户端
0类(内存)
0类(磁盘)
1行处理
U3000 U3000
我们可以看到,逻辑IO已经从原来的17355138到11974倍的下降,与水平的提高。执行时间也下降了超过3秒的时间从原来的近3分钟。很明显,性能有了很大的提高,但是我们看到有一个全表扫描表中在执行计划xstfxps1。总的来说,我们应该尽量避免全表扫描的存在,特别是对于大型的表,和适当的指标应设置避免FTS的一代。让我们在两个表的索引信息一看:
U3000 U3000
选择index_name,从dba_ind_columns哪里table_name like'xstfxps % column_name
index_name column_name
-----------------------------------------------------------------
xstfxps1_pk dhao00
xstfxps2_pk dhao00
xstfxps2_pk spdm00
U3000 U3000
我们看到除了主键约束外,这两个表没有其他索引,根据语句的查询情况,我们建立了下列复合索引:
创建xstfxps1指数idx_xstfxps1_khdm00_ywrq00(khdm00,ywrq00)表索引;
U3000 U3000
为了使用指标,我们必须对原有的日期字段的条件作一些调整。声明不会使用索引因为一个trunc()函数的存在。只要我们明白TRUNC(ywrq00)= trunc(SYSDATE)实际上是在ywrq00 TRUNC(系统日期),小于trunc(SYSDATE + 1)减一次,我们有一个更好的方式来处理它。
这个条件。最后重写的语句如下所示:
选择和(sl0000)
从xstfxps2,xstfxps1 B
在a.dhao00 = b.dhao00
和b.khdm00 = '500000003913
和b.ywrq00之间trunc(SYSDATE)
TRUNC(SYSDATE)+1 /(24×60×60);
执行计划
----------------------------------------------------------
0选择语句优化器=选择
10类(合计)
21表的访问(通过索引rowid)of'xstfxps2
32嵌套循环
43表的访问(通过索引rowid)of'xstfxps1
54指数(范围扫描)of'idx_xstfxps1_khdm00_ywrq00
(非唯一)
U3000 U3000
63指数(范围扫描)of'xstfxps2_pk(独特的)
统计
----------------------------------------------------------
0递归调用
0分贝块得到
3一致的获取
0物理读
0重做日志大小
210个字节通过网络发送给客户机
从客户端接收的275个字节
2 SQL*Net切换到/从客户端
0类(内存)
0类(磁盘)
1行处理
在这个时候,我们看到,逻辑IO已经减少到3倍,而且执行计划的句子也符合我们的调整目标,所创建的索引有更大的影响。