SQL优化

SQL优化

    • 1.在表中建立索引,优先考虑where.group by使用到的字段。
    • 2.查询条件中,一定不要使用select * ,因为会返回过多无用的字段会降低查询效率,增加数据传输时间。应该使用具体的字段代替,只返回使用到的字段。
    • 3.不要在where条件中使用左右两边都是%的like模糊查询,如:
    • 4.尽量不要使用in 和not in,会造成全表扫描。如:
    • 5.尽量不要使用or,会造成全表扫描。如下:
    • 6.尽量不要在 where 子句中对字段进行表达式操作,这样也会造成全表扫描。如:
    • 7.where条件里尽量不要进行null值的判断,null的判断也会造成全表扫描。如下:
    • 8.尽量不要在where条件中等号的左侧进行表达式.函数操作,会导致全表扫描。如下:
    • 9.尽量不要使用where 1=1的条件
    • 11.一个表的索引数最好不要超过5个,如果索引太多的话,就需要考虑一下那些不常使用到的列上建的索引是否有必要。
    • 12.使用varchar代替char
    • 13.尽量使用数值替代字符串类型
    • 14.使用explain分析你SQL执行计划
    • 15.字符串怪现象
    • 16.索引不适合建在有大量重复数据的字段上
    • 17.避免在索引列上使用内置函数
    • 18.避免在where子句中使用!=或<>操作符
    • 19.去重distinct过滤字段要少
    • 20.where中使用默认值代替null
    • 21.union all代替union
    • 22.小表驱动大表
    • 23.连接查询代替子查询
    • 24.join的表不宜过多
    • 25.提升group by的效率

1.在表中建立索引,优先考虑where.group by使用到的字段。

2.查询条件中,一定不要使用select * ,因为会返回过多无用的字段会降低查询效率,增加数据传输时间。应该使用具体的字段代替,只返回使用到的字段。

3.不要在where条件中使用左右两边都是%的like模糊查询,如:

SELECT * FROM t_order WHERE customer LIKE ‘%zhang%’ 导致数据库引擎放弃索引进行全表扫描
优化:尽量在字段后面使用模糊查询。如下:
SELECT * FROM t_order WHERE customer LIKE ‘zhang%’

4.尽量不要使用in 和not in,会造成全表扫描。如:

SELECT * FROM t_order WHERE id IN (2,3)
SELECT * FROM t_order1 WHERE customer IN (SELECT customer FROM t_order2)
优化:对于连续的数值,能用 between 就不要用 in,如:SELECT * FROM t_order WHERE id BETWEEN 2 AND 3
对于子查询,可以用exists代替。如下:SELECT * FROM t_order1 WHERE EXISTS (SELECT * FROM t_order2 WHERE t1.customer = t2.customer)

5.尽量不要使用or,会造成全表扫描。如下:

SELECT * FROM t_order WHERE id = 1 OR id = 3
优化:可以用union代替or。如下:
SELECT * FROM t_order WHERE id = 1
UNION
SELECT * FROM t_order WHERE id = 3

6.尽量不要在 where 子句中对字段进行表达式操作,这样也会造成全表扫描。如:

select id FROM t_order where num/2=100
应改为:
select id FROM t_order where num=100*2

7.where条件里尽量不要进行null值的判断,null的判断也会造成全表扫描。如下:

SELECT * FROM t_order WHERE score IS NULL
优化:
给字段添加默认值,对默认值进行判断。如:
SELECT * FROM t_order WHERE score = 0

8.尽量不要在where条件中等号的左侧进行表达式.函数操作,会导致全表扫描。如下:

SELECT * FROM t_order2 WHERE score/10 = 10
SELECT * FROM t_order2 WHERE SUBSTR(customer,1,5) = ‘zhang’
优化:
将表达式.函数操作移动到等号右侧。如下:
SELECT * FROM t_order2 WHERE score = 10*10
SELECT * FROM t_order2 WHERE customer LIKE ‘zhang%’

9.尽量不要使用where 1=1的条件

会造成进行全表扫描。如下:
SELECT * FROM t_order WHERE 1=1
优化:如果用代码拼装sql,则由代码进行判断,没where加where,有where加and
如果用mybatis,请用mybatis的where语法。
10.程序要尽量避免大事务操作,提高系统并发能力。

11.一个表的索引数最好不要超过5个,如果索引太多的话,就需要考虑一下那些不常使用到的列上建的索引是否有必要。

索引并不是越多越好,虽其提高了查询的效率,但却会降低插入和更新的效率
索引可以理解为一个就是一张表,其可以存储数据,其数据就要占空间
再者,索引表的一个特点,其数据是排序的,那排序要不要花时间呢?肯定要
insert或update时有可能会重建索引,如果数据量巨大,重建将进行记录的重新排序,所以建索引需要慎重考虑,视具体情况来定
一个表的索引数最好不要超过5个,若太多需要考虑一些索引是否有存在的必要

12.使用varchar代替char

varchar变长字段按数据内容实际长度存储,存储空间小,可以节省存储空间
char按声明大小存储,不足补空格
其次对于查询来说,在一个相对较小的字段内搜索,效率更高

13.尽量使用数值替代字符串类型

14.使用explain分析你SQL执行计划

15.字符串怪现象

SELECT * FROM student WHERE NAME=123,走全表,name为varchar类型,db会将所有name转换为整形再去查询

16.索引不适合建在有大量重复数据的字段上

如性别字段。因为SQL优化器是根据表中数据量来进行查询优化的,如果索引
列有大量重复数据,Mysql查询优化器推算发现不走索引的成本更低,很可能就放弃索引了。

17.避免在索引列上使用内置函数

使用索引列上内置函数索引失效

18.避免在where子句中使用!=或<>操作符

应尽量避免在where子句中使用!=或<>操作符,否则引擎将放弃使用索引而进行全表扫描。记住实现业务优先,实在没办法,就只能使用,并不是不能使用。如果不能使用,SQL也就无需支持了。

19.去重distinct过滤字段要少

带distinct的语句占用cpu时间高于不带distinct的语句。因为当查询很多字段时,如果使用distinct,数据库引擎就会对数据进行比较,过滤掉重复数据,然而这个比较、过滤的过程会占用系统资源,如cpu时间

20.where中使用默认值代替null

并不是说使用了is null 或者 is not null 就会不走索引了,这个跟mysql版本以及查询成本都有关
如果mysql优化器发现,走索引比不走索引成本还要高,就会放弃索引,这些条件 !=,<>,is null,is not null经常被认为让索引失效,其实是因为一般情况下,查询的成本高,优化器自动放弃索引的
如果把null值,换成默认值,很多时候让走索引成为可能,同时,表达意思也相对清晰一点

21.union all代替union

union会去重,所以会重复性扫描

22.小表驱动大表

子查询中:in适合左边大表,右边小表,因为先执行右边SQL

exists适合左边小表,右边大表

inner join关联,mysql会自动选择两张表中的小表,去驱动大表,所以性能上不会有太大的问题。

能用inner join的地方,尽量少用left join。

23.连接查询代替子查询

缺点是mysql执行子查询时,需要创建临时表,查询完毕后,需要再删除这些临时表,有一些额外的性能消耗。

24.join的表不宜过多

根据阿里巴巴开发者手册的规定,join表的数量不应该超过3个。

并发量不大,但业务比较复杂,需要join十几张表才能查询出数据,可以试试冗余一下数据

所以join表的数量要根据系统的实际情况决定,不能一概而论,尽量越少越好。

25.提升group by的效率

通常它会跟having一起配合使用,表示分组后再根据一定的条件过滤数据。

反例:

select user_id,user_name from order
group by user_id
having user_id <= 200;

这种写法性能不好,它先把所有的订单根据用户id分组之后,再去过滤用户id大于等于200的用户。

分组是一个相对耗时的操作,为什么我们不先缩小数据的范围之后,再分组呢?

正例:

select user_id,user_name from order
where user_id <= 200
group by user_id

的操作,为什么我们不先缩小数据的范围之后,再分组呢?

正例:

select user_id,user_name from order
where user_id <= 200
group by user_id

索引优化等

你可能感兴趣的:(sql,数据库)