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