因为项目需求,要求解决程式效率问题,于是我对sql下手了
学习了一天记录下来的sql优化注意事项!!!!!!!!总结下来如下几点,后期有必要再增加
1. 对查询进行优化,应尽量避免全表扫描,首先应该考虑在where及order by 涉及的列上建立索引
2. 应尽量避免在where字句中对字段进行null值判断,否则将导致引擎放弃索引而进行全表扫描,如:
select id from ums_account where num is null
可以在num上设置默认值0,确保num没有null值,然后这样查询:
select id from ums_account where num = 0
3.应尽量避免在where子句中使用 != 或者 <> 操作符,否则引擎将放弃使用索引而进行全表扫描。
4.应尽量避免在where子句中使用or来连接条件,否则将导致引擎放弃索引而进行全表扫描,如:
select id from ums_account where emp_no='00102' or emp_no='00202'
可以这样查询
select id from ums_account where emp_no='00102' union all select id from ums_account where emp_no='00202'
5. in和 not in 也要慎用,否则会导致全表扫描,如:
select id from ums_account where role_id in (1,2,3)
对于连续的数值,能用between 就不要用in 了;
select id from ums_account where role_id between 1 and 3
6.用like查询时,“%” 在前会导致全表扫描,如'%aaa',在后不会,如'aaa%'
7.应尽量避免在where字句中对字段进行表达式操作,这将导致索引失效而进行全表扫描。如:
select id from ums_account where num/2=100
应改为:
select id from ums_account where num= 100*2
8.应尽量避免在where子句中对字段进行函数操作,这将导致索引失效进行全表扫描。如查询username以amy开头的id:
select id from ums_account where substring(username,1,3)='amy'
应改为:
select id from ums_account where username like 'amy%'
9.不要在where子句中的 "=" 左边进行函数,算数运算或其他表达式运算,否则可能会导致索引无法正确使用。
10.在使用索引字段作为条件时,如果索引是复合索引,那么必须使用该索引中的第一个字段作为条件才能保证系统使用该索引,否则该索引将不会被使用,并且应尽可能的让字段顺序与索引顺序相一致。
11.不要写一些没有意义的查询,如需要生成一个空表结构:
select co11,co12 into #t from t where 1=0
这类代码不会返回任何结果集,但是会消耗系统资源,应改成这样
create table #t(...)
12. 很多时候用exists代替in是一个好的选择
SELECT id FROM `ums_account` WHERE id IN (SELECT mall_account_id FROM `ums_account_third_party`)
用一下语句替换:
SELECT ua.id FROM ums_account ua WHERE EXISTS (SELECT 1 FROM `ums_account_third_party` uat WHERE uat.mall_account_id=ua.id)
exists表示存在,指的是至少存在一处,这个条件有exists子查询来完成,但是这里exists子查询返回的结果却不再是一个结果集,而是一个布尔值(true 或 false),其实这个挺好理解的,exists就是表示如果子查询能查到值则返回true,则用exists之前的语句。
13. 并不是所有索引都对查询有效,SQL是根据表中数据来进行查询优化的,档索引列有大量数据重复时,sql查询可能不会去利用索引,如一个表中有字段sex,字段的值男,女几乎各一半,那么即使在sex上建立了索引也对查询效率起不了作用
14. 索引并不是越多越好,索引固然可以提高相应的select的效率,但同时也降低了insert及update的效率
因为insert或update时有可能会重建索引,所以怎样建索引需要慎重选择,视情况而定
15. 尽量使用数据型字段,若只含数值信息的字段尽量不要设计为字符型,这样会降低查询和连接的性能,并会增加存储开销。
这是因为引擎在处理查询和连接时会逐个标胶字符串中的每一个字符,而对于数字型而言只需要比较一次就够了
16. 尽可能的使用varchar代替char,因为首先变长字段存储空间小,可以节省空间,其次对于查询来说,在一个相对较小的字段内搜索效率显然高些。
17. 任何地方都不要使用select * from t ,用具体的字段列表代替“*”,不要返回用不到的任何字段。
18. 避免频繁创建和删除临时表,以减少系统表资源的消耗。
19. 临时表并不是不可使用,适当的使用他们可以使某些例程更有效,例如,当需要重复引用大型表或常用表中的某个数据集时。但是对于一次性事件,最好使用导出表。
20.在新建临时表时,如果一次性插入数据量很大,那么可以使用 select into 代替 create table,避免造成大量 log , 以提高速度;如果数据量不大,为了缓和系统表的资源,应先create table,然后insert。
select into from 和insert into select 都是用来复制表,两者的主要区别为:select into from要求目标表不存在,因为在插入时会自动创建。insert into select 要求目标表存在
21. 如果使用到了临时表,在存储过程的最后务必将所有的临时表显示删除,先truncate table,然后drop table,这样可以避免系统表的较长时间锁定。
22. 尽量避免使用游标,因为游标的效率较差,如果游标操作的数据超过1万行,那么就考虑改写。
23. 尽量避免大事务操作,提高系统并发能力。
24. 尽量避免向客户端返回大数据量,若数据量过大,应该考虑相应需求是否合理