如何写出性能好的sql
开发人员是很少注意SQL对数据库性能影响的重要性的,大多程序员都会认为SQL是比较简单的,需要的时候查查手册就可以了,很少有深究的。
这样的观念对大型系统的开发是致命的,需要纠正这样的观念。
造成这样的原因,可能有如下几种:
1,对数据库性能的研究,成果不是显而易见,对程序员的成就感激励不足,因为开发环境中的数据很少,数据库性能好坏体现不出来,好的sql和差的sql体现不出差别,所以,更多的人选择的是写出来就可以了,没有想到过性能。没有吃过这方面的亏,没有深刻的教训,人总是要有了教训才会重视,而以教训作为学习方法其实是很高成本的。
2,程序员更重视能写多少功能,会多少语言,对于一些不是显而易见和不好衡量的能力是不够重视的。
今天客户的一套系统因为一段sql没有考虑性能问题,导致数据在几万条数据的情况下,竟然也出现了巨大的性能开销,导致系统瘫痪无法使用的状况,所以,觉得有必要将一些心得写出来与大家共享。
索引是非常重要的,但是很多人是不重视的。
我总是不厌其烦的向很多开发人员介绍索引的重要性,但是,很多时候都可以从他们脸上看出来那种不以为然,但我还是在不厌其烦的向他们讲解,因为索引能否正确使用对系统的性能太重要了。
我觉得几个重要而简单的概念应该是必须掌握的:
a.聚集索引和非聚集索引,各应该用在什么场合
b.什么样的语句会使用索引,什么样的语句将不使用索引
c.应该在什么样的字段上面建立索引
d.复合索引的使用特点
一些具体的规则,如果不能理解,死记住也会获益
1,经常用来做联接的字段上面加索引
2,经常用来做条件的字段上面加索引
3,坚决避免在条件中使用否定意义的计算符,如:
select * from table1 where column1 not in (select column2 from table2)
select * from table1 where column1 not exists (select column2 from table2)
select * from table1 where id <> 100
4,聚集索引能对范围查询的性能产生巨大的提升,一定要善加利用,但是如果使用不当,也会带来巨大的性能损失
如你可以将一个订单表的订单日期加上聚集索引,订单日期是递增的,这样你按照日期范围查询时,你将获得最高的性能
select * from 客户订单 where 订单日期 between '2005-1-1' and '2005-1-31' --是范围的查询
但是你把客户编号作为聚集索引,将不会带来重大的性能提升,反而会有负效果,因为订单的顺序客户编号是非顺序的,这样由于聚集索引需要重新排列物理磁盘,这样将会给数据写入带来巨大的开销
5,不要在生成顺序不规则的字段上面加聚集索引,应该选择能够按照递增或递减顺序生成数据的字段作为聚集索引的字段
6,坚决避免对条件字段何作为连接的字段进行运算,甚至使用函数,如:
select * from UserInfo where firstname + lastname = 'Bill Gates'
select * from UserInfo where dbo.fGetBasicSalary(UserInfo.UserId) = 2000
select * from table1 inner join table2 on table1.A + table1.B = table2.C
7,建立索引是有必要的,但不是越多越好
8,可能的话,主键多用整型值,用一个整型字段做连接,比一个字符串在大数据量的情况下性能会提高很多
9,不要把大数量的内容放到 in ()里面,如避免如下写法:
select * from table1 where column1 in (select column2 from table2) --如果此时table2的数据量比较大的情况下,性能将会非常差
其实类似的语句经常可以改写为连接的方式来实现
10,经常用来Order By的字段加上索引,也会有性能的提升
11,子查询不要出现太多,大多数能够使用外连接来替代
select *,
(select z1 from T1 where z2=T2.Id) z1,
(select z2 from T1 where z2=T2.Id) z2,
(select z3 from T1 where z2=T2.Id) z3,
from T2
这段语句肯定不是优化的,会有性能问题的,可以有如下的方式来改写
select *, T1.Z1, T1.Z2, T1.Z3
from T2 left outer join T1 on T1.Z2 = T2.ID
12,对于like的使用
推荐:select * from 用户 where 姓名 like '李%'
不推荐:select * from 用户 where 姓名 like '%白%'
建议:
写点东西算作抛砖引玉吧,希望能给一些数据库初学者一些指引和建议吧!
还有就是,如果我们的系统出现了性能的问题,多从软件的角度来考虑优化,而不是动不动就要求客户升级服务器,硬件的改善对性能的提升能力是很有限的,提高一倍,两倍都是很厉害的了,而软件的优化有时候能起到数十倍,上百倍,甚至更高的性能提升。
呼吁大家提高对数据性能的重视。
查看执行时间
declare @d datetime
set @d=getdate()
并在select语句后加:
select [语句执行花费时间(毫秒)]=datediff(ms,@d,getdate())
如何写出性能好的sql的更多相关文章
- 写出易调试的SQL(修订版)
h4 { background: #698B22 !important; color: #FFFFFF; font-family: "微软雅黑", "宋体", ...
- 写出易调试的SQL
h4 { background: #698B22 !important; color: #FFFFFF; font-family: "微软雅黑", "宋体", ...
- 写出易调试的SQL—西科软件
1.前言 上篇 写出易调试的SQL , 带来了一些讨论, 暴露了不能重用执行计划和sql注入问题, 十分感谢园友们的建议 . 经过调整后 ,将原来的SQLHelper 抓SQL 用做调试环境用, 发布 ...
- Mysql写出高质量的sql语句的几点建议
CleverCode在实际的工作也写过一些低效率的sql语句.这些语句会给数据库带来非常大的压力.最基本的表现就是sql语句执行慢,后来逐渐的去优化和尝试. 总结了一些高质量的sql语句的写法.这里C ...
- 写出易于调试的SQL
1.前言 相比高级语言的调试如C# , 调试SQL是件痛苦的事 . 特别是那些上千行的存储过程, 更是我等码农的噩梦. 在将上千行存储过程的SQL 分解到 C# 管理后, 也存在调试的不通畅, 如何让 ...
- Oracle 如何写出高效的 SQL
转自:Oracle 如何写出高效的 SQL 要想写出高效的SQL 语句需要掌握一些基本原则,如果你违反了这些原则,一般情况下SQL 的性能将会很差. 1. 减少数据库访问次数连接数据库是非常耗时的,虽 ...
- 数据库性能调优——sql语句优化(转载及整理) —— 篇1
一.问题的提出 在应用系统开发初期,由于开发数据库数据比较少,对于查询SQL语句,复杂视图的的编写等体会不出SQL语句各种写法的性能优劣,但是如果将应用系统提交实 ...
- 数据库性能优化之SQL语句优化
一.问题的提出 在应用系统开发初期,由于开发数据库数据比较少,对于查询SQL语句,复杂视图的编写等是体会不出SQL语句各种写法的性能优劣,但是如果将应用系统提交实际应用后,随着数据库中数据的增加,系统 ...
- 数据库性能优化之SQL语句优化(上)
一.问题的提出 在应用系统开发初期,由于开发数据库数据比较少,对于查询SQL语句,复杂视图的编写等体会不出SQL语句各种写法的性能优劣,但是如果将应用系统提交实际应用后,随着数据库中数据的增加,系统的 ...
随机推荐
- PHP 7 值得期待的新特性(上)
这是我们期待已久的 PHP 7 系列文章的第一篇. 或许你已经知道了,我在 PHP 5.0.0 时间轴 提的 RFC (Request For Comments)通过了, PHP 7 成为 PHP 下 ...
- SetTimer在无窗口和有窗口线程的使用 . .
今天犯了一个粗心的错误,在无窗口线程中,SetTimer中设置计时器ID,而WM_TIMER消息响应函数中得到的计时器ID却不是之前设置的计时器ID. 对应计时器ID的输出的是一个随机数字. 原来在m ...
- OSharp框架总体设计
OSharp框架解说系列(1):总体设计 〇.前言 哈,距离前一个系列<MVC实用构架设计>的烂尾篇(2013年9月1日)已经跨了两个年头了,今天是2015年1月9日,日期已经相映,让我们 ...
- php中对共享内存,消息队列的操作
http://www.cnblogs.com/fengwei/archive/2012/09/12/2682646.html php作为脚本程序,通常生命周期都很短,如在web应用中,一次请求就是ph ...
- 你想建设一个能承受500万PV/每天的网站吗?
(如果感觉有帮助,请帮忙点推荐,添加关注,谢谢!你的支持是我不断更新文章的动力.本博客会逐步推出一系列的关于大型网站架构.分布式应用.设计模式.架构模式等方面的系列文章) 你想建设一个能承受500万P ...
- python的常用概念
常用的概念 主体字符串 主体列表 内置函数和方法的区别 映射表 引用 迭代器: 1. 字典:单步遍历迭代器 2. 文件:逐行读取的迭代器
- 蓝牙(3)如何通过蓝牙传输数据及UUID详介
如何通过蓝牙传输数据 通过蓝牙传输数据与Socket类似.在网络中使用Socket和ServerSocket控制客户端和服务端的数据读写.而蓝牙通讯也由客户端和服务端Socket来完成.蓝牙客户端So ...
- [HIS] HIT行业常用名词及缩写定义
[HIS] HIT行业常用名词及缩写定义 1. EHR 居民个人电子健康记录 2. MPI 居民个人主索引 3. HIS 医院管理信息系统 4. CIS 医院临床信息系统 5. P ...
- [POJ 2588] Snakes
同swustoj 8 Snakes Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 1015 Accepted: 341 ...
- java中两种类型变量
Java中有两种类型的变量,一种是对象类型,另一种是基础类型(primitive type). 对象类型普遍采用引用的方式,比如 List a = new ArrayList(); List b = ...