SELECT * FROM t_order WHERE customer LIKE ‘%zhang%’ 导致数据库引擎放弃索引进行全表扫描
优化:尽量在字段后面使用模糊查询。如下:
SELECT * FROM t_order WHERE customer LIKE ‘zhang%’
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)
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
select id FROM t_order where num/2=100
应改为:
select id FROM t_order where num=100*2
SELECT * FROM t_order WHERE score IS NULL
优化:
给字段添加默认值,对默认值进行判断。如:
SELECT * FROM t_order WHERE score = 0
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%’
会造成进行全表扫描。如下:
SELECT * FROM t_order WHERE 1=1
优化:如果用代码拼装sql,则由代码进行判断,没where加where,有where加and
如果用mybatis,请用mybatis的where语法。
10.程序要尽量避免大事务操作,提高系统并发能力。
索引并不是越多越好,虽其提高了查询的效率,但却会降低插入和更新的效率
索引可以理解为一个就是一张表,其可以存储数据,其数据就要占空间
再者,索引表的一个特点,其数据是排序的,那排序要不要花时间呢?肯定要
insert或update时有可能会重建索引,如果数据量巨大,重建将进行记录的重新排序,所以建索引需要慎重考虑,视具体情况来定
一个表的索引数最好不要超过5个,若太多需要考虑一些索引是否有存在的必要
varchar变长字段按数据内容实际长度存储,存储空间小,可以节省存储空间
char按声明大小存储,不足补空格
其次对于查询来说,在一个相对较小的字段内搜索,效率更高
SELECT * FROM student WHERE NAME=123,走全表,name为varchar类型,db会将所有name转换为整形再去查询
如性别字段。因为SQL优化器是根据表中数据量来进行查询优化的,如果索引
列有大量重复数据,Mysql查询优化器推算发现不走索引的成本更低,很可能就放弃索引了。
使用索引列上内置函数索引失效
应尽量避免在where子句中使用!=或<>操作符,否则引擎将放弃使用索引而进行全表扫描。记住实现业务优先,实在没办法,就只能使用,并不是不能使用。如果不能使用,SQL也就无需支持了。
带distinct的语句占用cpu时间高于不带distinct的语句。因为当查询很多字段时,如果使用distinct,数据库引擎就会对数据进行比较,过滤掉重复数据,然而这个比较、过滤的过程会占用系统资源,如cpu时间
并不是说使用了is null 或者 is not null 就会不走索引了,这个跟mysql版本以及查询成本都有关
如果mysql优化器发现,走索引比不走索引成本还要高,就会放弃索引,这些条件 !=,<>,is null,is not null经常被认为让索引失效,其实是因为一般情况下,查询的成本高,优化器自动放弃索引的
如果把null值,换成默认值,很多时候让走索引成为可能,同时,表达意思也相对清晰一点
union会去重,所以会重复性扫描
子查询中:in适合左边大表,右边小表,因为先执行右边SQL
exists适合左边小表,右边大表
inner join关联,mysql会自动选择两张表中的小表,去驱动大表,所以性能上不会有太大的问题。
能用inner join的地方,尽量少用left join。
缺点是mysql执行子查询时,需要创建临时表,查询完毕后,需要再删除这些临时表,有一些额外的性能消耗。
根据阿里巴巴开发者手册的规定,join表的数量不应该超过3个。
并发量不大,但业务比较复杂,需要join十几张表才能查询出数据,可以试试冗余一下数据
所以join表的数量要根据系统的实际情况决定,不能一概而论,尽量越少越好。
通常它会跟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
…
索引优化等