分享一个SQL优化经验
2011-07-13 09:22
344 查看
很长时间没有搞SQL了,最近又回归原始,有一个优化的经验和大家分享下。
看下面一个查询,这是查询学生数据的逻辑,逻辑比较有点乱,这个查询跑30分钟也不会出结果,一执行CPU立马100%,虽然是个虚似机,但也不至于这种查询也对付不了,肯定有优化的地方。
SELECT * FROM 学生表 WITH(NOLOCK) WHERE
(FromSys IS NULL OR
(
(FromSys<>'A' AND FromSys<>'B' AND FromSys<>'C') OR
(
(FromSys='A' OR FromSys='B' OR FromSys='C')
AND FromSysID NOT IN(SELECT OriginID FROM 学生表 WITH(NOLOCK) WHERE DataFlag=0)
)
)
)
上面的代码看起来有点乱,其实整理一下,条件就是三类:
1:FromSys IS NULL。
2:FromSys<>'A' AND FromSys<>'B' AND FromSys<>'C'。
3:(FromSys='A' OR FromSys='B' OR FromSys='C') AND FromSysID NOT IN(SELECT OriginID FROM 学生表 WITH(NOLOCK) WHERE DataFlag=0)
)
优化点如下:
第一:把上面的第一个和第二个条件or换成union all,主要是因为过多的or查询,有可能会引起表扫描,致使性能下降,这里就不做比较了。
第二,把第三个or里面的not in 用left join 代替,这种写法还要感谢我上家公司的DBA,他们教会我不少SQL知识,嘿嘿。
left join sql:
SELECT COUNT(*) FROM (
SELECT *
FROM 学生表 WITH(NOLOCK) WHERE
FromSys IN ('A','B','C' )
) AS tem LEFT JOIN dbo.学生表 s2 ON tem.FromSysID=s2.OriginID AND s2.DataFlag=0
WHERE s2.FromSysID IS null
下面是left join的执行计划图,很清晰,很简单。
not in sql:
SELECT COUNT(*) FROM 学生表 WITH(NOLOCK) WHERE
(FromSys='A' OR FromSys='B' OR FromSys='C')
AND FromSysID NOT IN(SELECT OriginID FROM 学生表 WITH(NOLOCK) WHERE DataFlag=0)
下面是not in的执行计划图,复杂得多,而且有多个嵌套查询。
第三:创建相应索引,其实对于非专业DBA,有时不太容易去优化SQL语句,但目前sql 2008有一个特别简单的功能,可以从预估执行计划中得出需要创建的索引,我们参考一下就行:
第四:如果一个条件中过多的or,例如:FromSys='A' OR FromSys='B' OR FromSys='C',可以用in来代码,这样代码会精简一些。
效果:最终使执行30分钟都无结果的操作,控制下几秒内完成,不可思议啊,继续学习。
看下面一个查询,这是查询学生数据的逻辑,逻辑比较有点乱,这个查询跑30分钟也不会出结果,一执行CPU立马100%,虽然是个虚似机,但也不至于这种查询也对付不了,肯定有优化的地方。
SELECT * FROM 学生表 WITH(NOLOCK) WHERE
(FromSys IS NULL OR
(
(FromSys<>'A' AND FromSys<>'B' AND FromSys<>'C') OR
(
(FromSys='A' OR FromSys='B' OR FromSys='C')
AND FromSysID NOT IN(SELECT OriginID FROM 学生表 WITH(NOLOCK) WHERE DataFlag=0)
)
)
)
上面的代码看起来有点乱,其实整理一下,条件就是三类:
1:FromSys IS NULL。
2:FromSys<>'A' AND FromSys<>'B' AND FromSys<>'C'。
3:(FromSys='A' OR FromSys='B' OR FromSys='C') AND FromSysID NOT IN(SELECT OriginID FROM 学生表 WITH(NOLOCK) WHERE DataFlag=0)
)
优化点如下:
第一:把上面的第一个和第二个条件or换成union all,主要是因为过多的or查询,有可能会引起表扫描,致使性能下降,这里就不做比较了。
第二,把第三个or里面的not in 用left join 代替,这种写法还要感谢我上家公司的DBA,他们教会我不少SQL知识,嘿嘿。
left join sql:
SELECT COUNT(*) FROM (
SELECT *
FROM 学生表 WITH(NOLOCK) WHERE
FromSys IN ('A','B','C' )
) AS tem LEFT JOIN dbo.学生表 s2 ON tem.FromSysID=s2.OriginID AND s2.DataFlag=0
WHERE s2.FromSysID IS null
下面是left join的执行计划图,很清晰,很简单。
not in sql:
SELECT COUNT(*) FROM 学生表 WITH(NOLOCK) WHERE
(FromSys='A' OR FromSys='B' OR FromSys='C')
AND FromSysID NOT IN(SELECT OriginID FROM 学生表 WITH(NOLOCK) WHERE DataFlag=0)
下面是not in的执行计划图,复杂得多,而且有多个嵌套查询。
第三:创建相应索引,其实对于非专业DBA,有时不太容易去优化SQL语句,但目前sql 2008有一个特别简单的功能,可以从预估执行计划中得出需要创建的索引,我们参考一下就行:
第四:如果一个条件中过多的or,例如:FromSys='A' OR FromSys='B' OR FromSys='C',可以用in来代码,这样代码会精简一些。
效果:最终使执行30分钟都无结果的操作,控制下几秒内完成,不可思议啊,继续学习。
相关文章推荐
- 给大家分享一个SQL优化经验
- mysql分页时offset过大的Sql优化经验分享
- sql优化经验分享
- SQL性能优化案例:分享一次系统迁移获得的经验
- SQL语句优化--十条经验
- 博客内容优化的经验分享
- [置顶] 一个Web报表项目的性能分析和优化实践(一):小试牛刀,统一显示SQL语句执行时间
- sql优化经验记录
- 一个老兵的linux学习和面试经验分享 【转载】
- SQL 优化经验总结34条
- 一个老兵的linux学习和面试经验分享
- 高手详解SQL性能优化十条经验
- 经验分享(六)一个程序员给初学编程人的建议!绝对的好!!
- 分享一个网站网站防火墙。功能说明:防护XSS,SQL,代码执行,文件包含等多种高危漏洞
- 3年前的一个小项目经验,分享给菜鸟兄弟们(公文收发小软件:小技能 SmallDatetime)
- 一个程序员在Elance上的外包经验分享
- mysql数据库索引查询一个优化大数据量的实例的分享
- mysql一个用户SQL慢查询分析,原因及优化
- 将一个网站在一个月内将四个关键词都做到第一页的经验分享
- 提高mysql千万级大数据SQL查询优化30条经验(Mysql索引优化注意)