大部分表都有表示逻辑删除的字段,比如is_valid,Y为有效N为无效,写sql时大部分都会带上这个字段,所以建索引时,建议带上这个字段。
比如student表有name列,如果只对name列建索引,where name = ‘xxx’ and is_valid = ‘Y’,索引不生效,应该建(name, is_valid)联合索引
尽量少在mysql做函数计算,容易成为性能瓶颈,建议把函数计算上移到应用层,即java代码。
比如需要查找时间入参前一天的数据,可以这样写: where date = date_add(#{时间入参}, interval -1 DAY),也可以在java层把时间入参减一天,再传到mysql,这样就是 where date = #{时间入参}
尽量使用覆盖索引,覆盖索引不需要回表(回表需要随机IO),explain的extra列有using index表示用上了覆盖索引。
假设有一个学生表,有id name age is_valid四个列,现在有一个根据年龄查询有效姓名的功能,想要用上覆盖索引,索引该怎么建?
答案: KEY idx_age_valid_name
(age
,is_valid
,name
)
explain select name from student where age = 30 and is_valid = 'Y';
image.png如果是select * from a join b where xxx这种写法,会对a和b求笛卡尔积,然后根据条件过滤数据,笛卡尔积非常大,性能极差,因此最好写成select * from a join b on xxx这种写法,结果完全等价。
注意:只有join可以这样等价替换,left join和right join不行
select部分有子查询时,最好自定义PageHelper分页
select
(select a from t1 where xxx) as a,
(select b from t2 where xxx) as b
from t3
使用PageHelper时,会先count一下原sql统计总数用于分页。
对于上面这种sql,select count(上面的sql)与select count(*) from t3结果一样,但是前者耗时更长,如果用PageHelper分页,默认使用前者,需要自定义为后者。
假设原sql的标签为<select id='queryT3'>,可以写一个<select id='queryT3_COUNT>',PageHelper会根据_COUNT后缀判断是否为自定义count函数。
深分页问题
先查id,再用in查数据
网友评论