SlideShare a Scribd company logo
1 of 24
SQL语句编写优化和基本原理总结


           王崇安 2012-08-24
   http://wangchongan.com
   http://weibo.com/wangchongan




                 欢迎访问技术博客: wangchongan.com
共享SQL语句
为不重复解析相同的SQL,在第一次解析后,ORACLE将会把SQL语句存放在内存中
(SGA的共享池中),以在下次执行同样的SQL时直接获得解析后的SQL及最好的执行路径。

注意:ORACLE只对单表提供高速缓冲,不适用于多表连接查询。

共享语句必须满足3个条件:
1、字符级的比较
如:select * from wl_trade; 和 select *   from wl_trade; 不同
2、两个语句所指的对象必须完全相同
3、两个SQL语句中比如使用相同的名字的绑定变量。
   (赋值相同也不行)                                    用户         对象名          访问类型
                                               lpwl    lp_trade     private synonym
                                                       lp_product   public synonym
                                               lpoc    lp_trade     private synonym
                                                       lp_product   public synonym
Overview of SGA
 System global area (SGA)
 The SGA is a group of shared memory structures, known as SGA components, that contain data and
 control information for one Oracle Database instance. The SGA is shared by all server and background
 processes. Examples of data stored in the SGA include cached data blocks and shared SQL areas.




资料来源:http://docs.oracle.com/cd/B28359_01/server.111/b28318/memory.htm
表名顺序(在RBO中)
• 按照表记录数: 大 -> 小
• 表书写顺序:  左 -> 右
因为表间连接时,最右边的表会被放到嵌套循环的最外层。最外层循环
越少,效率越高。
WHERE子句中条件的顺序
ORACLE采用自下而上(自右向左)的顺序解析WHERE子句。

 表之间的连接必须写在其他条件之前

 可以过滤掉最大记录的条件必须写在WHERE子句末尾


 应用场景举例:查找某个SPU的所有订单的基本信息

                              SQL语句                             性能效果
 Select t.trade_id, o.order_id, o.product_id from wl_trade t,
 wl_order o where o.product_id = ‘289098760’ and t.id =          低效
 o.inner_trade_id

 Select t.trade_id, o.order_id, o.product_id from wl_trade t,
 wl_order o where t.id = o.inner_trade_id and o.product_id =     高效
 ‘289098760’
SELECT子句中避免使用*
• 需列出全部的COLUMN时,不建议使用*
因为ORACLE在解析SQL的过程中会将*转换成所有的列名,这个环节是通过
查数据字典完成的,意味性能的损耗。
删除重复记录
• 最高效的删除重复记录的方法
  场景举例:删除手工单引起的重复的销售订单

 delete from wl_trade t1
 where t1.rowid > (
        select min(x.rowid)
        from wl_trade t2
        where t2.trade_id = t1.trade_id);

 因为使用ROWID,所以高效
•
           用TRUNCATE替代DELETE
     表记录删除时,采用回滚段(rollback segments)来存放可以被恢复的信息。rollback时oracle将
     会将数据恢复到执行删除命令前的状况。
•    而当使用truncate时,回滚段不再存放可恢复信息。资源利用少,响应快。
•    delete属DML,truncate属DDL(隐式事务,会自动提交)
•    delete将被删数据块标记为无效(unused),truncate将表的高水位线HWM标为0
•    再扫描时,delete后的数据由于高水位线没有变化,还是会扫描原来所有数据块,性能差


     应用场景举例:4PL监控看板统计任务定时truncate
•
                   多使用COMMIT
    由上条大至推理可知:尽可能地多使用COMMIT,但,还不止这个原因。。。



COMMIT所释放的资源:

1、回滚段上用于恢复数据的信息

2、被程序语句获得的锁。如:4PL中库存更新操作(下图)

3、redo log buffer中的空间

4、为管理上面资源的内部花费
用WHERE子句替换HAVING子句
• HAVING中的条件一般用于集合函数的比较,如count(),否则一
    般条件应写在WHERE子句中
 因为HAVING只会在检索出所有记录后才进行对结果集的过滤,这个处理需要总计或排序
 等操作。如果通过WHERE子句限制记录条数,就能减少这个开销。



  应用场景举例:4PL监控看板中计算合单量SQL

SELECT G.LSO_FATHER_ID                      SELECT G.LSO_FATHER_ID
 FROM WL_MONITOR_GRAND_ORDER G               FROM WL_MONITOR_GRAND_ORDER G
WHERE G.LSO_FATHER_ID != 0                   WHERE
 AND G.O_PRODUCT_ID = '10000'                 G.O_PRODUCT_ID = '10000'
 AND G.T_PLATFORM_CODE = 'TB'                 AND G.T_PLATFORM_CODE = 'TB'
 AND G.T_SUPPLIER_CHANNEL = 0                 AND G.T_SUPPLIER_CHANNEL = 0
 AND G.O_GMT_PAY >= '2012-08-01 00:00:00'     AND G.O_GMT_PAY >= '2012-08-01 00:00:00'
 AND G.O_GMT_PAY <= '2012-08-21 00:00:00'     AND G.O_GMT_PAY <= '2012-08-21 00:00:00'
 AND G.O_PAY_STATUS != 'TRADE_CLOSED'         AND G.O_PAY_STATUS != 'TRADE_CLOSED'
 AND G.LSO_IS_DELETED='N'                     AND G.LSO_IS_DELETED='N'
GROUP BY G.LSO_FATHER_ID                     GROUP BY G.LSO_FATHER_ID
HAVING COUNT(G.LSO_FATHER_ID)>1             HAVING COUNT(G.LSO_FATHER_ID)>1
                                              AND G.LSO_FATHER_ID != 0
EXISTS?IN?
并不是简单的都要使用EXISTS替代IN
in是对外表和内表作Hash Join(哈希连接)
而exist是对外表和内表做了一个Nested loop(嵌套连接)

 例如:表A(小表),表B(大表),CC列上有索引
select * from A where cc in (select cc from B) – 低效
A是小表,CC索引优势不明显,B表索引没充分利用


select * from A where exists(select cc from B where cc=A.cc) – 高效
遍历A,但小表次数也少,用到了B表索引

补充点:Not in内外表都做全表扫描,没用到索引,而Not exists子查询仍能用到索引

                                  子句                  使用策略
                         EXISTS                  小表大表
                         IN                      大表小表
                         NOT EXISTS              尽量用
                         NOT IN                  尽量不用
用EXISTS替换DISTINCT
• 一对多表查询时,避免使用DISTINCT,可考虑用EXISTS替
  换

   应用场景举例:查询所有被用户购买过的4PL-SPU

                           SQL                  idb测试用时   比较

 select distinct p.id
   from wl_product p, wl_logistics_suborder o             性能低
 where p.id = o.spu_id

 select p.id
   from wl_product p
  where exists (select 1                                  性能高
                from wl_logistics_suborder o
              where o.spu_id = p.id)
用EXPLAIN PLAN分析SQL
解读顺序:从里至外,从上至下,同层操作最小操作号先解读
ORACLE对索引访问模式
•   唯一索引扫描(index unique scan)

    返回单个ROWID,存在UNIQUE或PRIMARY KEY时

•   索引范围扫描(index range scan)

    存取多行数据,在唯一索引上使用范围操作符 (>, <, >=, <=, between)

    组合索引上,只使用部分列进行查询,导致查询出多行

    对非唯一索引上的任何查询

•   索引全扫描(index full scan)

    查询返回的字段必须全部来自索引

•   索引快速扫描(index fast full scan)

    扫描索引中的所有数据块,与index full scan显著区别是不对结果集排序,基于该特点可使用多块读、

并行读以提高吞吐量和缩短时间。
索引选择之唯一和非唯一索引
• 如果查询条件存在使用唯一和非唯一索引,则
  ORACLE将使用唯一索引,完全忽略非唯一索引
索引选择之多个平级索引
•   唯一性索引优先级高于非唯一性索引

    只适用于索引列和常量比较

•   相同表中同等级索引时

    WHERE子句中最先被引用的索引优先级高

•   不同表间同等级索引时

    FROM子句表顺序右至左,右边表的索引优先被使用

•   多表多索引均可使用时

    ORACLE会同时使用并对记录进行合并,检索出对所有索引都有效的记录
索引选择之等式和范围比较
• WHERE子句有索引列但ORACLE无法合并使
  用,将采用范围比较




 LPWL.WL_ORDER_IND6:只有PRODUCT_Id的索引被用到
索引选择之不明确的索引等级
• 当ORACLE无法确定索引的等级时,一般来说优化器将使用WHERE子句
 最前面那个。

  但ORACLE也很聪明
强制索引失效
• 通过+number 或 || varchar 形式可使索引失效
一般强制索引失效的调优仅用于个别SQL,
绝大部分情况下ORACLE本身已能选择很佳的执行路径。

在使用索引失效前需确认好索引列是否已建索引?


 场景举例:查询某商品指定SKU的销售订单

  前提:product_id、skuid 分别有非唯一索引

select * from wl_order where
product_id = ‘18513216738’ and skuid = ‘20979202070’;

select * from wl_order where
product_id || ‘’ = ‘18513216738’ and skuid = ‘20979202070’;
避免在索引列使用NULL或NOT NULL
• 单例索引如包含空值,索引中不存在此记录
• 联合索引中列全空,索引中不存在此记录
• 联合索引中存在至少一列不为空,索引中存在此记录
总是使用组合索引第一列
• 如果是组合索引,则只有第一列使用时,优化器才会使用
  该索引
 举例演示:测试4PL的wl_order表的WL_ORDER_SID_IND(SUPPLIER_ID,LOGISTICS_STATUS)索引



                                 使用了第一列SUPPLIER_ID,优化器走了索引




                        不使用第一列SUPPLIER_ID,导致全表扫描
简单飘过
1.   不要在索引列上使用计算
2.   不要在索引列上使用NOT
3.   用 >= 替代 >
4.   避免改变索引列的类型
5.   !=号可能导致不走索引
• 监控看板案例      使用Hints-案例分析




不匹配的别名导致执行路径不生效,执行约2分钟                     调整后很快,约200ms

  延伸知识:
  1. ordered根据 from 后面表的顺序join,从左到右,左边的表做驱动表
  2. /*+use_nl(t2,t) */ 提示走nest loop,但没有提示t2还是t为驱动表
  3. /*+ ordered use_nl(t2,t) */提示走nest loop,order提示的是from后面的第一个表为驱动表
  4. /*+ leading(t2) use_nl(t) */ 直接提示t2为驱动表

  结论:use_nl不能让优化器确定谁是驱动表谁是被驱动的表,use_nl(t,t2)也没有指出哪个是驱
  动表,这时候我们需要使用ordered,leading来强制指定驱动表,以达到我们的目的
谢谢大家!

More Related Content

What's hot

Mysql的索引及优化策略
Mysql的索引及优化策略Mysql的索引及优化策略
Mysql的索引及优化策略fog001
 
Kid171 chap03 traditional Chinese Version
Kid171 chap03 traditional Chinese VersionKid171 chap03 traditional Chinese Version
Kid171 chap03 traditional Chinese VersionFrank S.C. Tseng
 
Java SE 8 技術手冊第 14 章 - NIO 與 NIO2
Java SE 8 技術手冊第 14 章 - NIO 與 NIO2Java SE 8 技術手冊第 14 章 - NIO 與 NIO2
Java SE 8 技術手冊第 14 章 - NIO 與 NIO2Justin Lin
 
Sql Server 高级技巧系列之三整体优化
Sql Server 高级技巧系列之三整体优化Sql Server 高级技巧系列之三整体优化
Sql Server 高级技巧系列之三整体优化向 翔
 
PostGIS 初入門應用
PostGIS 初入門應用PostGIS 初入門應用
PostGIS 初入門應用Chengtao Lin
 
Java SE 8 技術手冊第 5 章 - 物件封裝
Java SE 8 技術手冊第 5 章 - 物件封裝Java SE 8 技術手冊第 5 章 - 物件封裝
Java SE 8 技術手冊第 5 章 - 物件封裝Justin Lin
 
Java SE 7 技術手冊投影片第 10 章 - 輸入輸出
Java SE 7 技術手冊投影片第 10 章 - 輸入輸出Java SE 7 技術手冊投影片第 10 章 - 輸入輸出
Java SE 7 技術手冊投影片第 10 章 - 輸入輸出Justin Lin
 
Sql Server 高级技巧系列之一:索引详解
Sql Server 高级技巧系列之一:索引详解Sql Server 高级技巧系列之一:索引详解
Sql Server 高级技巧系列之一:索引详解向 翔
 
Oracle 資料庫檔案介紹
Oracle 資料庫檔案介紹Oracle 資料庫檔案介紹
Oracle 資料庫檔案介紹Chien Chung Shen
 
5, initialization & cleanup
5, initialization & cleanup5, initialization & cleanup
5, initialization & cleanupted-xu
 

What's hot (13)

Mysql的索引及优化策略
Mysql的索引及优化策略Mysql的索引及优化策略
Mysql的索引及优化策略
 
Kid171 chap03 traditional Chinese Version
Kid171 chap03 traditional Chinese VersionKid171 chap03 traditional Chinese Version
Kid171 chap03 traditional Chinese Version
 
Java SE 8 技術手冊第 14 章 - NIO 與 NIO2
Java SE 8 技術手冊第 14 章 - NIO 與 NIO2Java SE 8 技術手冊第 14 章 - NIO 與 NIO2
Java SE 8 技術手冊第 14 章 - NIO 與 NIO2
 
Sql Server 高级技巧系列之三整体优化
Sql Server 高级技巧系列之三整体优化Sql Server 高级技巧系列之三整体优化
Sql Server 高级技巧系列之三整体优化
 
Spark tutorial
Spark tutorialSpark tutorial
Spark tutorial
 
PostGIS 初入門應用
PostGIS 初入門應用PostGIS 初入門應用
PostGIS 初入門應用
 
Java SE 8 技術手冊第 5 章 - 物件封裝
Java SE 8 技術手冊第 5 章 - 物件封裝Java SE 8 技術手冊第 5 章 - 物件封裝
Java SE 8 技術手冊第 5 章 - 物件封裝
 
11
1111
11
 
Java SE 7 技術手冊投影片第 10 章 - 輸入輸出
Java SE 7 技術手冊投影片第 10 章 - 輸入輸出Java SE 7 技術手冊投影片第 10 章 - 輸入輸出
Java SE 7 技術手冊投影片第 10 章 - 輸入輸出
 
Sql Server 高级技巧系列之一:索引详解
Sql Server 高级技巧系列之一:索引详解Sql Server 高级技巧系列之一:索引详解
Sql Server 高级技巧系列之一:索引详解
 
Oracle 資料庫檔案介紹
Oracle 資料庫檔案介紹Oracle 資料庫檔案介紹
Oracle 資料庫檔案介紹
 
Oracle 資料庫建立
Oracle 資料庫建立Oracle 資料庫建立
Oracle 資料庫建立
 
5, initialization & cleanup
5, initialization & cleanup5, initialization & cleanup
5, initialization & cleanup
 

Similar to Sql语句编写优化和基本原理总结

诗檀软件 Oracle开发优化基础
诗檀软件 Oracle开发优化基础 诗檀软件 Oracle开发优化基础
诗檀软件 Oracle开发优化基础 maclean liu
 
My sql数据库开发的三十六条军规
My sql数据库开发的三十六条军规My sql数据库开发的三十六条军规
My sql数据库开发的三十六条军规isnull
 
MySQL数据库开发的三十六条军规
MySQL数据库开发的三十六条军规MySQL数据库开发的三十六条军规
MySQL数据库开发的三十六条军规mysqlops
 
Mysql数据库开发的三十六条军规 石展_完整
Mysql数据库开发的三十六条军规 石展_完整Mysql数据库开发的三十六条军规 石展_完整
Mysql数据库开发的三十六条军规 石展_完整Yousri Yan
 
第9章 t sql程序设计
第9章 t sql程序设计第9章 t sql程序设计
第9章 t sql程序设计hanmo1988
 
资身Dba经验谈
资身Dba经验谈资身Dba经验谈
资身Dba经验谈yiditushe
 
A.oracle 查询结果的缓存问题
A.oracle 查询结果的缓存问题A.oracle 查询结果的缓存问题
A.oracle 查询结果的缓存问题WASecurity
 
Azure Data Lake 簡介
Azure Data Lake 簡介Azure Data Lake 簡介
Azure Data Lake 簡介Herman Wu
 
10, OCP - flashback
10, OCP - flashback10, OCP - flashback
10, OCP - flashbackted-xu
 
数据库性能诊断的七种武器
数据库性能诊断的七种武器数据库性能诊断的七种武器
数据库性能诊断的七种武器Leyi (Kamus) Zhang
 
5, OCP - oracle storage
5, OCP - oracle storage5, OCP - oracle storage
5, OCP - oracle storageted-xu
 
分区表基础知识培训
分区表基础知识培训分区表基础知识培训
分区表基础知识培训maclean liu
 
腾讯大讲堂48 数据库查询优化浅析
腾讯大讲堂48 数据库查询优化浅析腾讯大讲堂48 数据库查询优化浅析
腾讯大讲堂48 数据库查询优化浅析George Ang
 
11, OCP - awr & alert system
11, OCP - awr & alert system11, OCP - awr & alert system
11, OCP - awr & alert systemted-xu
 
Itpub电子杂志第四期第二稿
Itpub电子杂志第四期第二稿Itpub电子杂志第四期第二稿
Itpub电子杂志第四期第二稿yiditushe
 
MySQL运维那些事
MySQL运维那些事 MySQL运维那些事
MySQL运维那些事 Leo Zhou
 
Mysql fast share
Mysql fast shareMysql fast share
Mysql fast sharerfyiamcool
 
【Ask maclean技术分享】oracle dba技能列表 z
【Ask maclean技术分享】oracle dba技能列表 z【Ask maclean技术分享】oracle dba技能列表 z
【Ask maclean技术分享】oracle dba技能列表 zmaclean liu
 

Similar to Sql语句编写优化和基本原理总结 (20)

诗檀软件 Oracle开发优化基础
诗檀软件 Oracle开发优化基础 诗檀软件 Oracle开发优化基础
诗檀软件 Oracle开发优化基础
 
My sql数据库开发的三十六条军规
My sql数据库开发的三十六条军规My sql数据库开发的三十六条军规
My sql数据库开发的三十六条军规
 
MySQL数据库开发的三十六条军规
MySQL数据库开发的三十六条军规MySQL数据库开发的三十六条军规
MySQL数据库开发的三十六条军规
 
Mysql数据库开发的三十六条军规 石展_完整
Mysql数据库开发的三十六条军规 石展_完整Mysql数据库开发的三十六条军规 石展_完整
Mysql数据库开发的三十六条军规 石展_完整
 
第9章 t sql程序设计
第9章 t sql程序设计第9章 t sql程序设计
第9章 t sql程序设计
 
资身Dba经验谈
资身Dba经验谈资身Dba经验谈
资身Dba经验谈
 
Oracle Tablespace介紹
Oracle Tablespace介紹Oracle Tablespace介紹
Oracle Tablespace介紹
 
A.oracle 查询结果的缓存问题
A.oracle 查询结果的缓存问题A.oracle 查询结果的缓存问题
A.oracle 查询结果的缓存问题
 
Azure Data Lake 簡介
Azure Data Lake 簡介Azure Data Lake 簡介
Azure Data Lake 簡介
 
10, OCP - flashback
10, OCP - flashback10, OCP - flashback
10, OCP - flashback
 
数据库性能诊断的七种武器
数据库性能诊断的七种武器数据库性能诊断的七种武器
数据库性能诊断的七种武器
 
HW4_0711282.pdf
HW4_0711282.pdfHW4_0711282.pdf
HW4_0711282.pdf
 
5, OCP - oracle storage
5, OCP - oracle storage5, OCP - oracle storage
5, OCP - oracle storage
 
分区表基础知识培训
分区表基础知识培训分区表基础知识培训
分区表基础知识培训
 
腾讯大讲堂48 数据库查询优化浅析
腾讯大讲堂48 数据库查询优化浅析腾讯大讲堂48 数据库查询优化浅析
腾讯大讲堂48 数据库查询优化浅析
 
11, OCP - awr & alert system
11, OCP - awr & alert system11, OCP - awr & alert system
11, OCP - awr & alert system
 
Itpub电子杂志第四期第二稿
Itpub电子杂志第四期第二稿Itpub电子杂志第四期第二稿
Itpub电子杂志第四期第二稿
 
MySQL运维那些事
MySQL运维那些事 MySQL运维那些事
MySQL运维那些事
 
Mysql fast share
Mysql fast shareMysql fast share
Mysql fast share
 
【Ask maclean技术分享】oracle dba技能列表 z
【Ask maclean技术分享】oracle dba技能列表 z【Ask maclean技术分享】oracle dba技能列表 z
【Ask maclean技术分享】oracle dba技能列表 z
 

Sql语句编写优化和基本原理总结