sql 优化建议

1、查询语句,尽量避免查询全部,避免写 select * from table,查哪个写哪个,提高效率;

更新语句,能update具体字段的,不要update所有字段,提升效率。

要尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引

2、一张表中添加索引太少不行,索引的添加可以让查询速度变快,但是索引太多,新增操作会变慢,

一般一张表中索引不要超过6个

3、应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,

如:select id from t where num is null

最好不要给数据库留NULL,尽可能的使用 NOT NULL填充数据库.

备注、描述、评论之类的可以设置为 NULL,其他的,最好不要使用NULL。

不要以为 NULL 不需要空间,

如:char(100) 型,在字段建立时,空间就固定了, 不管是否插入值(NULL也包含在内),都是占用 100个字符的空间的,如果是varchar这样的变长字段, null 不占用空间。

可以在num上设置默认值0,确保表中num列没有null值,然后这样查询select id from t where num = 0

4、应尽量避免在 where 子句中使用 != 或 <> 操作符,否则将引擎放弃使用索引而进行全表扫描。

5、应尽量避免在 where 子句中使用 or 来连接条件,如果一个字段有索引,一个字段没有索引,将导致引擎放弃使用索引而进行全表扫描,如:select id from t where num=10 or Name = ‘admin’

可以这样查询:

select id from t where num = 10

union all

select id from t where Name = ‘admin’

6、避免在 where 子句中对字段进行表达式操作,这将导致引擎放弃使用索引而进行全表扫描

select id from t where num/2 = 100

可以改为:

select id from t where num = 100*2

7、避免在where子句中对字段进行函数操作,这将导致引擎放弃使用索引而进行全表扫描

select id from t where substring(name,1,3) = ’abc’ -–name以abc开头的id

select id from t where datediff(day,createdate,’2005-11-30′) = 0 -–‘2005-11-30’ –生成的id

可以改为:

select id from t where name like ‘abc%’

select id from t where createdate >= ‘2005-11-30’ and createdate < ‘2005-12-1’

8、in 和 not in 也要慎用,否则会导致全表扫描,如:select id from t where num in(1,2,3)

对于连续的数值,能用 between 就不要用 in 了:

select id from t where num between 1 and 3

用 exists 代替 in 是一个好的选择:

select num from a where num in(select num from b)

可以改为:

select num from a where exists(select 1 from b where num=a.num)

9、like模糊查询也将导致全表扫描:

select id from t where name like ‘%abc%’

可以在界面上使用下拉菜单,让用户选择的方式,或者ajax弹出匹配的关键字,然后再查询。

若要提高效率,可以考虑全文检索(Lucene或者solr)。

10、尽量使用数字型字段,若只含数值信息的字段尽量不要设计为字符型,这会降低查询和连接的性能,

并会增加存储开销。这是因为引擎在处理查询和连 接时会逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次就够了。

11、在新建临时表时,如果一次性插入数据量很大,那么可以使用 select into 代替 create table,避免造成大量 log ,以提高速度;如果数据量不大,为了缓和系统表的资源,应先create table,然后insert。

12、如果使用到了临时表,在存储过程的最后务必将所有的临时表显式删除,先 truncate table ,然后 drop table ,这样可以避免系统表的较长时间锁定。

13、尽量避免使用游标,因为游标的效率较差,如果游标操作的数据超过1万行,那么就应该考虑改写。(至于游标呢,可以把游标当作一个指针,它可以指定结果中的任何位置,然后允许用户对指定位置的数据进行处理)

14、在可以使用UNION ALL的语句里,尽量使用,最好不要使用了UNION。

15、用>=替代> 往往会高效

高效:SELECT * FROM EMP WHERE DEPTNO >=4

低效: SELECT * FROM EMP WHERE DEPTNO >3

两者的区别在于,前者DBMS将直接跳到第一个DEPT等于4的记录而后者将首先定位到DEPTNO=3的记录并且向前扫描到第一个DEPT大于3的记录。

16、多数数据库都是从 左到右的顺序处理条件,把能过滤更多数据的条件放在前面,过滤少的条件放后面

select * from employee

where salary >1000 –条件1,过滤的数据较少

and dept_id=’01’ –条件2,过滤的数据比条件1多

上面的SQL就不符合我们的原则了,应该把过滤数据更多的条件放在前面,因此改为下面这样更好

select * from employee

where dept_id=’01’ –过滤更多数据的条件放在前面

and salary > 1000

当然,Oracle数据库的where条件处理顺序是从右向左的。

17、实际案例分析:拆分大的 DELETE 或INSERT 语句,批量提交SQL语句

如果你需要在一个在线的网站上去执行一个大的 DELETE 或 INSERT 查询,你需要非常小心,要避免你的操作让你的整个网站停止相应。因为这两个操作是会锁表的,表一锁住了,别的操作都进不来了。Apache 会有很多的子进程或线程。所以,其工作起来相当有效率,而我们的服务器也不希望有太多的子进程,线程和数据库链接,这是极大的占服务器资源的事情,尤其是内存。

如果你把你的表锁上一段时间,比如30秒钟,那么对于一个有很高访问量的站点来说,这30秒所积累的访问进程/线程,数据库链接,打开的文件数,可能不仅仅会让你的WEB服务崩溃,还可能会让你的整台服务器马上挂掉。

所以,如果你有一个大的处理,你一定把其拆分,使用 LIMIT oracle(rownum),sqlserver(top)条件是一个好的方法。下面是一个mysql示例:

《sql 优化建议》 这是一张图

18、总结不要在建立的索引的数据列上进行下列操作:

避免对索引字段进行计算操作

避免在索引字段上使用not,<>,!=

避免在索引列上使用IS NULL和IS NOT NULL

避免在索引列上出现数据类型转换

避免在索引字段上使用函数

避免建立索引的列中使用空值。

结束!! 希望给各位猿友带来帮助吧!!! 偷偷告诉你们!!!这是我刚写的日记!!

    原文作者:小刀嘚吧嘚
    原文地址: https://www.jianshu.com/p/5ee0b8edf507
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞