30条书写高质量SQL的建议,太有用了!( 二 )


把% 放关键字后面,还是会走索引的,如下图:

30条书写高质量SQL的建议,太有用了!

文章插图
 
6、使用 where 条件限定要查询的数据,避免返回多余的行
假设业务场景是这样:查询某个用户是否是会员 。曾经看过老的实现代码是这样 。
反例:
List<Long> userIds = sqlMap.queryList("select userId from user where isVip=1");boolean isVip = userIds.contains(userId);正例:
Long userId = sqlMap.queryObject("select userId from user where userId='userId' and isVip='1' ")boolean isVip = userId!=null;理由:需要什么数据,就去查什么数据,避免返回不必要的数据,节省开销 。
7、尽量避免在索引列上使用 MySQL 的内置函数
业务需求:查询最近七天内登陆过的用户(假设 loginTime 加了索引) 。
反例:
select userId,loginTime from loginuser where Date_ADD(loginTime,Interval 7 DAY) >=now(); 正例:
explain  select userId,loginTime from loginuser where  loginTime >= Date_ADD(NOW(),INTERVAL - 7 DAY); 理由:索引列上使用 MySQL 的内置函数,索引失效:
30条书写高质量SQL的建议,太有用了!

文章插图
 
如果索引列不加内置函数,索引还是会走的:
30条书写高质量SQL的建议,太有用了!

文章插图
 
8、应尽量避免在 where 子句中对字段进行表达式操作,这将导致系统放弃使用索引而进行全表扫
反例:
select * from user where age-1 =10; 正例:
select * from user where age =11; 理由:虽然 age 加了索引,但是因为对它进行运算,索引直接迷路了 。
30条书写高质量SQL的建议,太有用了!

文章插图
 
9、Inner join 、left join、right join,优先使用 Inner join,如果是 left join,左边表结果尽量小
Inner join 内连接,在两张表进行连接查询时,只保留两张表中完全匹配的结果集 。
left join 在两张表进行连接查询时,会返回左表所有的行,即使在右表中没有匹配的记录 。
right join 在两张表进行连接查询时,会返回右表所有的行,即使在左表中没有匹配的记录 。
都满足 SQL 需求的前提下,推荐优先使用 Inner join(内连接),如果要使用 left join,左边表数据结果尽量小,如果有条件的尽量放到左边处理 。
反例:
select * from tab1 t1 left join tab2 t2 on t1.size = t2.size where t1.id>2; 正例:
select * from (select * from tab1 where id >2) t1 left join tab2 t2 on t1.size = t2.size; 理由如下:
  • 如果 inner join 是等值连接,或许返回的行数比较少,所以性能相对会好一点 。
  • 同理,使用了左连接,左边表数据结果尽量小,条件尽量放到左边处理,意味着返回的行数可能比较少 。
10、应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描
反例:
select age,name from user where age <>18; 正例:
//可以考虑分开两条sql写select age,namefrom user where age <18;select age,namefrom user where age >18;理由:使用!=和<>很可能会让索引失效:
30条书写高质量SQL的建议,太有用了!

文章插图
 
11、使用联合索引时,注意索引列的顺序,一般遵循最左匹配原则
表结构:(有一个联合索引 idxuseridage,userId 在前,age 在后)
CREATE TABLE `user` (`id` int(11) NOT NULL AUTO_INCREMENT,`userId` int(11) NOT NULL,`age` int(11) DEFAULT NULL,`name` varchar(255) NOT NULL,PRIMARY KEY (`id`),KEY `idx_userid_age` (`userId`,`age`) USING BTREE) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;反例:
select * from user where age = 10; 
30条书写高质量SQL的建议,太有用了!

文章插图
 
正例:
//符合最左匹配原则select * from user where userid=10 and age =10;//符合最左匹配原则select * from user where userid =10;


推荐阅读