vlambda博客
学习文章列表

提高MYSQL千万级数据SQL查询优化经验

    比如说电商项目中,动辄上万个订单,亿以上级别的交易量,导致数据量很大,这个时候就考验我们的并发应对能力,尤其是SQL优化方面。


1. 对查询进行优化,应尽量避免全表扫描,首先应考虑在where及order by涉及的列上建立索引。

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

select name from student where number is null

    可以在number上设置默认值0,确保表中number列没有null值,可以这样查询:

select name from student where number = 0

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

4. 应尽量避免在where子句中使用or来连接条件,否则将导致引擎放弃使用索引而进行全表扫描。

select name from student where number = 10 or number = 20

可以这样查询:

select name from student where number = 10 union all select name from student where number = 20

5. in和not in也要慎用,如:select name from s where nnumber in(1,2,3)对于这样连续的数值,能用between就不要用in了。

6. 下面的查询也将导致全表扫描,若要提高效率,可以考虑全文检索。

select name from student where name like '%张%'

7. 如果在where子句中使用参数,也会导致全表扫描。因为SQL只有在运行时才会解析局部变量,但优化程序不能将访问计划的选择推迟到运行时;它必须在编译时进行选择。然而,如果在编译时建立访问计划,变量的值还是未知的,因为无法作为索引选择的输入项。如下语句将全表扫描:

select name from student where number = @num

可以改为强制查询使用索引:

select name from student with(index(索引名)) where nunmber = @num

8. 应尽量避免在where子句中对字段进行函数操作,这将导致引擎放弃索引使用全表扫描。

select number from student where id/2 = 10

9.  避免在where子句中对字段进行函数操作,如下直接使用like就行

select name from student where substring(name,1,3) = 'abc'

10. 不要在where子句中的‘=’左边进行函数、算术运算或者其他表达式运算。

11. 在使用索引字段作为条件时,如果该索引是复合索引,那么必须使用到该索引中的第一个字段作为条件时才能保证系统使用该索引,否则该索引将不会被使用,并且应尽可能的让字段顺序与索引顺序相一致。

12. 学会用exists代替in。

13. 并不是所有索引对查询都有效,SQL是根据表中数据来进行查询优化的,当索引列有大量数据重复时,SQL查询可能不会去利用索引,如一表中有字段sex、male、female几乎各一半,那么即使在sex建了索引也对查询效率起不了作用。

14. 索引并不是越多越好,索引固然可以提高相应的select的效率,但同时也降低了insert和update的效率,因为insert或者update又可能会重新建立索引,所以怎样建索引需要慎重考虑,视具体情况而定吧。

15. 尽量使用数字型字段,若只含数值信息的字段尽量不要设计为字符型,这会降低查询和连接的性能,并会增加存储开销。

16. 任何地方都不要使用select * from,用具体的字段代替‘*’,不要返回用不到的字段。

17. 避免频繁创建和删除临时表,以减少系统表资源的消耗。

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

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

20. 尽量避免大事务操作,提高系统并发能力。

21. 尽量避免向客户端返回大数据量,若数据量过大,应该考虑相应需求是否合理。