开发人员是很少注意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的更多相关文章

  1. 写出易调试的SQL(修订版)

    h4 { background: #698B22 !important; color: #FFFFFF; font-family: "微软雅黑", "宋体", ...

  2. 写出易调试的SQL

    h4 { background: #698B22 !important; color: #FFFFFF; font-family: "微软雅黑", "宋体", ...

  3. 写出易调试的SQL—西科软件

    1.前言 上篇 写出易调试的SQL , 带来了一些讨论, 暴露了不能重用执行计划和sql注入问题, 十分感谢园友们的建议 . 经过调整后 ,将原来的SQLHelper 抓SQL 用做调试环境用, 发布 ...

  4. Mysql写出高质量的sql语句的几点建议

    CleverCode在实际的工作也写过一些低效率的sql语句.这些语句会给数据库带来非常大的压力.最基本的表现就是sql语句执行慢,后来逐渐的去优化和尝试. 总结了一些高质量的sql语句的写法.这里C ...

  5. 写出易于调试的SQL

    1.前言 相比高级语言的调试如C# , 调试SQL是件痛苦的事 . 特别是那些上千行的存储过程, 更是我等码农的噩梦. 在将上千行存储过程的SQL 分解到 C# 管理后, 也存在调试的不通畅, 如何让 ...

  6. Oracle 如何写出高效的 SQL

    转自:Oracle 如何写出高效的 SQL 要想写出高效的SQL 语句需要掌握一些基本原则,如果你违反了这些原则,一般情况下SQL 的性能将会很差. 1. 减少数据库访问次数连接数据库是非常耗时的,虽 ...

  7. 数据库性能调优——sql语句优化(转载及整理) —— 篇1

    一.问题的提出                    在应用系统开发初期,由于开发数据库数据比较少,对于查询SQL语句,复杂视图的的编写等体会不出SQL语句各种写法的性能优劣,但是如果将应用系统提交实 ...

  8. 数据库性能优化之SQL语句优化

    一.问题的提出 在应用系统开发初期,由于开发数据库数据比较少,对于查询SQL语句,复杂视图的编写等是体会不出SQL语句各种写法的性能优劣,但是如果将应用系统提交实际应用后,随着数据库中数据的增加,系统 ...

  9. 数据库性能优化之SQL语句优化(上)

    一.问题的提出 在应用系统开发初期,由于开发数据库数据比较少,对于查询SQL语句,复杂视图的编写等体会不出SQL语句各种写法的性能优劣,但是如果将应用系统提交实际应用后,随着数据库中数据的增加,系统的 ...

随机推荐

  1. 1962-Fibonacci

    描述 This is an easy problem.I think Fibonacci sequence is familiar to you.Now there is another one. H ...

  2. GIT:本地有更改,但强制作远程仓库里作更新

    有时,紧急线上修改时,这个功能有用处的. git fetch --all git reset --hard origin/master ================ git reset --har ...

  3. jsp关于include html、jsp等文件出现乱码问题的解决方案

    一般来说使用jsp标签<jsp:include>引入一个jsp文件: ①可以在被引入的jsp中加入:<%@ page contentType="text/html;char ...

  4. Time.deltaTime 含义和应用

    第一種:使用Time.deltaTime 一秒內從第1個Frame到最後一個Frame所花的時間,所以不管電腦是一秒跑60格或者一秒30格.24格,值都會趨近於一. 就結果而言,deltaTime是為 ...

  5. eclipse中的输入提示怎么设置

    对于大多数的开发人员来说,打代码是一件非常繁琐的事情,eclipse中为我们提供了自动提示的功能,但是默认的提示只有当我们输入小数点后才能出现提示框,那么我们如何设置eclipse,能够让它为我们提示 ...

  6. Git教程(4)常用小技巧之标签

    Git 使用两种主要类型的标签:轻量标签(lightweight)与附注标签(annotated). 一个轻量标签很像一个不会改变的分支 - 它只是一个特定提交的引用. 然而,附注标签是存储在 Git ...

  7. 关于ckeditor添加的class都会被清除掉的问题

    在源码中输入ul,并且带有class,然后点击源码,到可视化界面 结果显示为aaa,再点看源码,查看HTML源代码 解决方法: 添加配置 config.allowedContent = true 这个 ...

  8. JavaScript window.open()属性

    一. Window 对象 Window 对象是 JavaScript 层级中的顶层对象. Window 对象代表一个浏览器窗口或一个框架. Window 对象会在 <body> 或 < ...

  9. ORACLE【2】:锁机制及解锁

    1. 锁的基本知识 根据要保护的对象不同,oracle的数据锁可以分成以下几类:DML锁,(data locks)数据锁,用于保护数据的完整性:DDL锁(dictionary locks),用于保护数 ...

  10. BZOJ2150: 部落战争

    题解: 把每个点拆成入点和出点,因为必须经过一次且只能经过一次.所以在两个点之间连一条上界=下界=1的边. 然后再s到每个入点连边,每个出点向t连边,点与点之间... 求最小流就可以过了... (感觉 ...