Sql 语句的优化 <ul><li>1 关于 sql 的语句分类 </li></ul><ul><li>2sql 语句的执行顺序 </li></ul><ul><li>3 说说 where 语句 </li></ul><ul><li>4 关于子查询的...
一、关于 sql 的语句分类 1.DDL 语句 用于建立各种数据库对象。(库、表、主键、外键、约束、索引。。。等) 2.DML 语句 insert  、 delete 、 update 3DCL 语句 各种权限控制语句
<ul><li>二、 sql 语句的执行顺序 </li></ul><ul><li>执行顺序从右往左执行。 </li></ul><ul><li>1. 插入语句  Insert into  table ( column1 ,  column12 ,...
<ul><li>三、说说 where 语句 </li></ul><ul><li>3.1 执行顺序。(从右往左 ,尽量在右边条件过滤掉大部分行) </li></ul><ul><li>根据业务逻辑调整条件,可以提高效率。  如  </li></ul...
<ul><li>四、关于子查询的巧用 </li></ul><ul><li>4.1  in  语句和子查询性能的万恶之源 </li></ul><ul><li>通信证的一个 sql 优化的例子: </li></ul><ul><li>我在原有的项目中...
<ul><li>原则一尽量使用系统函数 </li></ul><ul><li>(case when us.modelid is null then 0 else us.modelid end) mobid  </li></ul><ul><li>可...
<ul><li>最后我的优化语句为: ( 红色部分位修改 ) </li></ul><ul><li>select U.USERID userid, </li></ul><ul><li>U.MOBILE mobile, </li></ul><ul>...
<ul><li>4.2 几乎所有的子查询都能变为表连接( 我已经把表优化到最烂。呵呵! ) </li></ul><ul><li>请看 </li></ul><ul><li>Select  userid  ,  username ,  </li><...
<ul><li>五、 update  、 delete 和  insert  语句的技巧 </li></ul><ul><li>一次不只做一行,多行尽量做一次。 </li></ul><ul><li>5.1 Update 的技巧: </li></u...
<ul><li>六、关于关联的探讨 </li></ul><ul><li>查询表顺序的影响 </li></ul><ul><li>在 FROM 后面的表中的列表顺序会对 SQL 执行性能影响,在没有索引及 ORACLE 没有对表进行统计分析的情况下...
<ul><li>7. 一些细节的东西 </li></ul><ul><li>7.1Java 调用 sql 的提交尽量使用批量提交。 </li></ul><ul><li>7.2 存储过程会快很多。 </li></ul><ul><li>7.3 常用的...
<ul><li>7.5 一些例句: </li></ul><ul><li>1. 减少对表的查询 </li></ul><ul><li>SELECT TAB_NAME FROM TABLES WHERE (TAB_NAME,DB_VER) = ( S...
<ul><li>谢谢大家 </li></ul><ul><li>Sql 优化一言难尽 </li></ul>
Upcoming SlideShare
Loading in …5
×

Sql语句的优化

3,355
-1

Published on

sql语句优化的讨论

0 Comments
11 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
3,355
On Slideshare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
59
Comments
0
Likes
11
Embeds 0
No embeds

No notes for slide

Sql语句的优化

  1. 1. Sql 语句的优化 <ul><li>1 关于 sql 的语句分类 </li></ul><ul><li>2sql 语句的执行顺序 </li></ul><ul><li>3 说说 where 语句 </li></ul><ul><li>4 关于子查询的巧用 </li></ul><ul><li>5update 、 delete 和 insert 语句的技巧 </li></ul><ul><li>6 关于关联的探讨 </li></ul><ul><li>7 一些细节的东西 </li></ul>
  2. 2. 一、关于 sql 的语句分类 1.DDL 语句 用于建立各种数据库对象。(库、表、主键、外键、约束、索引。。。等) 2.DML 语句 insert 、 delete 、 update 3DCL 语句 各种权限控制语句
  3. 3. <ul><li>二、 sql 语句的执行顺序 </li></ul><ul><li>执行顺序从右往左执行。 </li></ul><ul><li>1. 插入语句 Insert into table ( column1 , column12 ,。。。) values ( value1,value2,… )的执行也是如此。 </li></ul><ul><li>2.Select 语句 </li></ul><ul><li>select 字段列表 from table where 条件 group by 字段列表 having 条件 order by 字段 ( desc|asc ) </li></ul><ul><li>执行顺序: where  group by ->having->order by ->select 列投影。 </li></ul><ul><li>其中 where 的条件和 having 的条件是从右往左执行。 </li></ul><ul><li>3.Update table set 字段设置 where 条件 </li></ul><ul><li>执行顺寻: where ->set->update </li></ul><ul><li>Where 条件从右往左执行。 </li></ul><ul><li>4delete from table where 条件 </li></ul><ul><li>执行顺序: where- 》 delete </li></ul><ul><li>Where 条件从右往左执行。 </li></ul><ul><li>总结:执行中的性能消耗主要在 where 语句的查询。 </li></ul>
  4. 4. <ul><li>三、说说 where 语句 </li></ul><ul><li>3.1 执行顺序。(从右往左 ,尽量在右边条件过滤掉大部分行) </li></ul><ul><li>根据业务逻辑调整条件,可以提高效率。 如 </li></ul><ul><li>where sex =' 男 ' and age >20 慢 </li></ul><ul><li>where age >20 and sex =' 男 ' 快 (因为按性别分可以一次过滤掉一半的行) </li></ul><ul><li>3.2 like 尽量少用。 </li></ul><ul><li>like 语句进行模糊查询较慢。 </li></ul><ul><li>3.3 between and 不如 > < 快 </li></ul><ul><li>where between 20 and 40; 慢 </li></ul><ul><li>where age >20 and age <40; 快 </li></ul><ul><li>3.4 in 和 exists </li></ul><ul><li>delete from userinfo where userid in ( select userid from user_status ); 慢 </li></ul><ul><li>delete from userinfo A where exists ( select B.userid from user_status B where A.userid = B.userid ); 快 </li></ul><ul><li>( 由于是 delete 语句难以 inner join) </li></ul>
  5. 5. <ul><li>四、关于子查询的巧用 </li></ul><ul><li>4.1 in 语句和子查询性能的万恶之源 </li></ul><ul><li>通信证的一个 sql 优化的例子: </li></ul><ul><li>我在原有的项目中找到如下代码:(将性能瓶颈进行标红) </li></ul><ul><li>select U.USERID userid, </li></ul><ul><li>U.MOBILE mobile, </li></ul><ul><li>U.USERNAME username, </li></ul><ul><li>U.USERTYPE userType, </li></ul><ul><li>US.LOGIN_TIMES, </li></ul><ul><li>US.LASTLOGIN_DT, </li></ul><ul><li>US.FREE_DL free_dl, </li></ul><ul><li>UP.nickname nickname, </li></ul><ul><li> (case when us.modelid is null then 0 else us.modelid end) mobid , </li></ul><ul><li>(select ml.MODEL_NAME </li></ul><ul><li>from model_list ml </li></ul><ul><li>where ml.modelid = US.MODELID) mobModel </li></ul><ul><li>from USERINFO U, USER_STATUS US, USER_PROFILE UP </li></ul><ul><li> where U.USERID = US.USERID </li></ul><ul><li> and U.USERID = UP.USERID </li></ul><ul><li> AND (U.STATUS = 1 or U.STATUS = 2) </li></ul><ul><li> and (U.USERNAME =’zhanghe’) </li></ul>
  6. 6. <ul><li>原则一尽量使用系统函数 </li></ul><ul><li>(case when us.modelid is null then 0 else us.modelid end) mobid </li></ul><ul><li>可以用标准函数替代 </li></ul><ul><li>Nvl(us.modelid , 0 ) </li></ul><ul><li>原则二避免列映射里面用子查询。 </li></ul><ul><li>(select ml.MODEL_NAME </li></ul><ul><li>from model_list ml </li></ul><ul><li>where ml.modelid = US.MODELID) mobModel </li></ul><ul><li>这部分可以放到关联中 </li></ul><ul><li>原则三查询条件不要总是马后炮 </li></ul><ul><li>from USERINFO U, USER_STATUS US, USER_PROFILE UP </li></ul><ul><li>where U.USERID = US.USERID </li></ul><ul><li> and U.USERID = UP.USERID </li></ul><ul><li> AND (U.STATUS = 1 or U.STATUS = 2) </li></ul><ul><li> and (U.USERNAME =’zhanghe’) </li></ul><ul><li>这部分可以将特定表的查询提前。 </li></ul>
  7. 7. <ul><li>最后我的优化语句为: ( 红色部分位修改 ) </li></ul><ul><li>select U.USERID userid, </li></ul><ul><li>U.MOBILE mobile, </li></ul><ul><li>U.USERNAME username, </li></ul><ul><li>U.USERTYPE userType, </li></ul><ul><li>US.LOGIN_TIMES, </li></ul><ul><li>US.LASTLOGIN_DT, </li></ul><ul><li>US.FREE_DL free_dl, </li></ul><ul><li>UP.nickname nickname, </li></ul><ul><li> nvl(us.modelid,0) mobid , </li></ul><ul><li>ml.MODEL_NAME mobModel </li></ul><ul><li>from </li></ul><ul><li>( select * USERINFO U where (U.STATUS = 1 or U.STATUS = 2 )and (U.USERNAME =’zhanghe’) </li></ul><ul><li>inner join USER_STATUS US on U.USERID = US.USERID </li></ul><ul><li>inner join USER_PROFILE UP on U.USERID = UP.USERID </li></ul><ul><li>left join model_list ml on ml.modelid = US.MODELID </li></ul>
  8. 8. <ul><li>4.2 几乎所有的子查询都能变为表连接( 我已经把表优化到最烂。呵呵! ) </li></ul><ul><li>请看 </li></ul><ul><li>Select userid , username , </li></ul><ul><li>( select logintime from user_status where userid = u.userid ) logintime </li></ul><ul><li>from userinfo u where userid in ( select userid from user_status where userid = u.userid ) </li></ul><ul><li>where ( userid = 1024 or userid = 1025 ) and sex = ‘ 男’ and username like ‘’ 张 %; </li></ul><ul><li>此语句是有一位张先生号码可能是 1024 或 1025 。 </li></ul><ul><li>请大家谈谈如何将此语句优化。 </li></ul><ul><li>大家优化后结果: </li></ul>
  9. 9. <ul><li>五、 update 、 delete 和 insert 语句的技巧 </li></ul><ul><li>一次不只做一行,多行尽量做一次。 </li></ul><ul><li>5.1 Update 的技巧: </li></ul><ul><li>使用 case 语句分修改分类条件 </li></ul><ul><li>Update userinfo set 说明 = </li></ul><ul><li>( case </li></ul><ul><li>when age > 20 and age <30 then ‘ 年轻’ </li></ul><ul><li>when age > 30 and age <40 then ‘ 健壮’ </li></ul><ul><li>) , </li></ul><ul><li>… .. </li></ul><ul><li>Where sex = ‘ 男’ </li></ul><ul><li>以此类推一条语句可以更新好多的条件和字段。 </li></ul><ul><li>5.2 insert 语句(不说也知道) </li></ul><ul><li>Insert into table1 ( id , username ) select userid , ‘ 张三’ from userinfo </li></ul><ul><li>5.3 delete 和 truncate 间的选择。 </li></ul><ul><li>Delete 有事物可回滚, truncate 不可回滚。 </li></ul>
  10. 10. <ul><li>六、关于关联的探讨 </li></ul><ul><li>查询表顺序的影响 </li></ul><ul><li>在 FROM 后面的表中的列表顺序会对 SQL 执行性能影响,在没有索引及 ORACLE 没有对表进行统计分析的情况下 ORACLE 会按表出现的顺序进行链接,由此因为表的顺序不对会产生十分耗服务器资源的数据交叉。(注:如果对表进行了统计分析, ORACLE 会自动先进小表的链接,再进行大表的链接) </li></ul><ul><li>From 表一 ,表二 ,表三 </li></ul><ul><li>From 表一 </li></ul><ul><li>Inner join 表二 </li></ul><ul><li>Inner join 表三 </li></ul><ul><li>以上的关联请将数据量最小的表放在后面, sql 是 从右往左 运行的。 </li></ul><ul><li>一些讨论: </li></ul><ul><li>客户 、订单、产品的关联。 </li></ul>
  11. 11. <ul><li>7. 一些细节的东西 </li></ul><ul><li>7.1Java 调用 sql 的提交尽量使用批量提交。 </li></ul><ul><li>7.2 存储过程会快很多。 </li></ul><ul><li>7.3 常用的复杂查询要写成 view 。 </li></ul><ul><li>7.4 尽量使用内部函数 </li></ul>
  12. 12. <ul><li>7.5 一些例句: </li></ul><ul><li>1. 减少对表的查询 </li></ul><ul><li>SELECT TAB_NAME FROM TABLES WHERE (TAB_NAME,DB_VER) = ( SELECT </li></ul><ul><li>TAB_NAME,DB_VER FROM TAB_COLUMNS WHERE VERSION = 604) </li></ul><ul><li>2. 用 EXISTS 替代 IN 、用 NOT EXISTS 替代 NOT IN : </li></ul><ul><li>(高效) SELECT * FROM EMP ( 基础表 )WHERE EMPNO > 0 AND EXISTS (SELECT ‘X' FROM DEPT </li></ul><ul><li>WHERE DEPT.DEPTNO = EMP.DEPTNO AND LOC = ‘MELB') </li></ul><ul><li>( 低效 )SELECT * FROM EMP ( 基础表 ) WHERE EMPNO > 0 AND DEPTNO IN(SELECT DEPTNO FROM DEPT WHERE LOC = ‘MELB') </li></ul><ul><li>3. 用 EXISTS 替换 DISTINCT : </li></ul><ul><li>( 低效 ):SELECT DISTINCT DEPT_NO,DEPT_NAME FROM DEPT D , EMP E </li></ul><ul><li>WHERE D.DEPT_NO = E.DEPT_NO </li></ul><ul><li>( 高效 ):SELECT DEPT_NO,DEPT_NAME FROM DEPT D WHERE EXISTS ( SELECT ‘X' </li></ul><ul><li>FROM EMP E WHERE E.DEPT_NO = D.DEPT_NO); </li></ul><ul><li>4. 用 >= 替代 > : </li></ul><ul><li>高效 :SELECT * FROM EMP WHERE DEPTNO >=4 </li></ul><ul><li>低效 :SELECT * FROM EMP WHERE DEPTNO >3 </li></ul><ul><li>5. 用 UNION 替换 OR ( 适用于索引列 ) : </li></ul><ul><li>高效 : SELECT LOC_ID , LOC_DESC , REGION FROM LOCATION WHERE LOC_ID = 10 </li></ul><ul><li>UNION </li></ul><ul><li>SELECT LOC_ID , LOC_DESC , REGION FROM LOCATION WHERE REGION = “MELBOURNE” </li></ul><ul><li>低效 :SELECT LOC_ID , LOC_DESC , REGION </li></ul><ul><li>FROM LOCATION </li></ul><ul><li>WHERE LOC_ID = 10 OR REGION = “MELBOURNE” </li></ul><ul><li>其他例子请看预习文档 </li></ul>
  13. 13. <ul><li>谢谢大家 </li></ul><ul><li>Sql 优化一言难尽 </li></ul>
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×