首次Oracle SQL Tuning经历

原创 2011年01月07日 18:06:00

这篇文章跟我一样的菜鸟可以看看。事情的缘由在上一篇Blog:如何判断程序处于I/O等待里面已经介绍过了。这件事情我也得到一个教训,QA环境和Production环境还是很不同的,特别是DB 操作,QA环境数据库数据量比较小,SQL执行计划在Production上可能得出完全不同的结果,而我的遭遇就是一条SQL在Production上一跑就再也回不来了,最后只好让DBA kill掉那个任务。

原来的SQL是这样的:一共牵涉5张表,表名和 每张表的索引情况如下:

Table Index Name Index Infomation
Table_Item Item_PK PRIMARY KEY (ID)
Table_Item Item_LM_IDX Last_Modified Asc
Table_Attr Attr_PK PRIMARY KEY (ID)
Table_Desc Desc_PK PRIMARY KEY (ID)
Table_Delay Delay_PK PRIMARY KEY (ID, PARTITION_KEY)
Table_Product Product_P_PK PRIMARY KEY(Product_ID)

select … from , Table_Desc , Table_Product , Table_Attr , Table_Delayed
where
(Table_Item.id = Table_Desc.id)
and (Table_Item.product_id = Table_Product.product_id(+))
and (Table_Item.id = Table_Attr.id(+))
and (Table_Item.id = Table_Delay.id(+))
and (Table_Item.last_modified between to_date( :start_time, ‘YYYY-MM-DD HH24:MI:SS’ )
                                                and to_date( :end_time , ‘YYYY-MM-DD HH24:MI:SS’ ) 
      )
order by Table_Item.last_modified;

使用的DB Hint 是:

/*+ index(table_item item_lm_idx) use_nl(table_delay) index(table_delay delay_pk) */

SQL>  explain plan for
select …

SQL>  @?/rdbms/admin/utlxpls

由于打印格式不同,我就不把执行计划贴出来了,执行情况良好:

  1. 所有的表都使用的了索引,Index Range Scan或者Index Unique Scan
  2. 执行Join的时候使用了Nested Loops或者Nested Loops Outer
  3. 没有发现Sort Join和Merge Join
  4. 没有发现Table Access Full –> Full Table Scan

我们发现即使在SQL中有order by table_item.last_modified,在SQL执行计划中也没有出现任何Sort有关的信息,一般在SQL中尽量不要使用order by,因为在DB Server端进行Sort是很耗费资源的。但是有一个例外,就是表中的数据已经排好序的情况下,我们这里就是这样的哦情况,执行计划中没有Sort是因为当从Table_Item表中以 Table_Item.last_modified between :start_time and :end_time取数据时,走的是Item_LM_IDX –>Last_Modified Asc, 所以取出来的数据本身已经按照last_modified 排好序了。

但是我更改过的SQL是这样的:

where Table_Item.last_modified=:start_time and Table_Item.ID>:last_id order by Table_Item.ID

让我悲哀的是这条修改过的SQL在有些数据库服务器上的执行计划是好的,有些不好。DBA给我的解释是并不是所有的表的统计信息都是更新过的,于是在那些统计信息没有更新的表上的执行计划很有可能就不对了。不如说这个:

00 SELECT STATEMENT
01     MERGE JOIN OUTER
02         NESTED LOOPS OUTER(将Item,Product,Desc的结果和Table_Delay进行Nested Join)
03             MERGE JOIN(由两个SORT JOIN的结果组成,得到Item,Product,Desc3张表的Join结果)
04                 SORT JOIN(将Table_Item和Table_Product的结果按照ID进行排序)
05                    NESTED LOOPS OUTER(将Table_Item和Table_Product进行Nested Outer Join)
06                         TABLE ACCESS BY INDEX ROWID   –> Table_Item
07                             INDEX RANGE SCAN                 –> Item_LM_IDX(使用Item_LM_IDX索引)
08                         TABLE ACCESS BY INDEX ROWID   –> Table_Product
09                             INDEX UNIQUE SCAN               –>  Product_P_PK
10                 SORT JOIN(将Table_Desc满足条件的记录按照ID进行排序)
11                    TABLE ACCESS BY INDEX ROWID       –> Table_Desc
12                          INDEX RANGE SCAN                   –>  RTable_DESC_PK
13             PARTITION RANGE ALL
14                 TABLE ACCESS BY LOCAL INDEX ROWID  –> Table_Delay
15                     INDEX RANGE SCAN                         –> Delay_PK
16         SORT JOIN
17             TABLE ACCESS FULL                                –> Table_Attr

注意到使用了很多Merge Sort,而处理Table_Attr的时候更是出现了Full Table Scan,更本就不使用索引。这里说句老实话,我不知道是不是应该DBA更新统计信息,重新给相关的表更新一下统计信息,还是就赶紧改一下DB Hint把自己的事情做完就算。不过我也理解的,Ebay的数据库太大了,不是随便想做什么就行的,最后我还是选择了修改DB Hint.

Ticket resolve的结果是,修改Db Hint :

/*+
index_asc(Table_Attr ATTR_PK)
index(Table_Item Item_LM_IDX)
use_nl(Table_Item Table_Attr Table_Desc Table_Delayed Table_Product) index(Table_Delay DELAY_PK)
index(Table_Product PRODUCT_P_PK)
index(Table_Desc RTable_DESC_PK)
*/

给所有的表都制定Index,建议Oracle对所有的表都使用Nested Loops Join。重新看一下执行计划:

00  SELECT STATEMENT
01      SORT ORDER BY
02          NESTED LOOPS OUTER
03              NESTED LOOPS OUTER
…(以下省略)

可以看到,修改DB Hint以后,只有对最后的结果进行SORT,这也是我们的初衷。没有SORT JOIN和Merge Join了。速度也快了很多。因为Ebay的DB是Split的,DBA为了保险,帮我把这条修改过的SQL对该数据库所有的Splits都运行了一次,才把Ticket标识成Resolved.

我刚把代码改了,添加了判断,如果运行新的SQL就使用修改的Hint。待会给QA测试,IDC的Sunil还不肯发BUG给我,因为他在QA环境没有观察到这个问题,甚至的Production StandBy DB也不能重现。这一点只能用楼上DBA的话来解释了:虽然是同一个DB的不同的Split,但是不同的Splits之间数据还是有差异,统计数据也不同,结果是影响Oracle做出判断,所以他们做SQL Review的时候都是要运行一下的,而不是光看看执行计划。

谢谢COC DBA Team的amao和alex给我上了一课。          

 

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

Oracle SQL tuning 步骤

SQL是的全称是Structured Query Language(结构化查询语言)。SQL是一个在80年代中期被使用的工业标准数据库查询语言。不要把SQL语言 与商业化产品如Microsoft S...

Oracle SQL tuning 步骤

SQL是的全称是Structured Query Language(结构化查询语言)。SQL是一个在80年代中期被使用的工业标准数据库查询语言。不要把SQL语言 与商业化产品如Microsoft S...

Automatic SQL Tuning in Oracle Database

oracle 10g可以使优化器运行在优化模式收集额外的信息,并且对当前sql做出一些建议,使其运行的更好。使用STA一定要保证优化器是CBO模式下。  在优化模式下,优化器可以给出以下的一些建议: ...

Oracle---Tip for SQL Database tuning and performance

Indexes(索引) 如果您是数据库的新手,甚至问自己“什么是SQL调优”,您应该知道索引是调整SQL数据库的有效方式,这在开发过程中经常被忽略。 在基本术语中,索引是一种数据结构,通过提供快速随...

SQL Tuning oracle 注册码:

  • 2009-12-21 17:56
  • 183B
  • 下载

利用oracle sql tuning advisor 进行sql调优

sql tunning advisor 使用的主要步骤:   1 建立tunning task   2 执行task  3 显示tunning 结果  4 根据建议来运行相应的调优方法下面来按照这个顺...

oracle11g中SQL优化(SQL TUNING)新特性之Adaptive Cursor Sharing (ACS)

oracle11g中最重要的特点之一——Adaptive Cursor Sharing (ACS),几乎完美的解决了之前版本不绑定不行,绑定也不行的尬尴问题,今天有机会对此特点再次进行研究和查阅资料,...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)