1.需求分析与普遍SQL写法
业务代码中,需要根据一个或多个条件,查询是否存在记录而不关心有多少条记录。普遍的SQL及代码写法如下:
select count(*) from the_table_name where ...
Java写法:
int nums = xxDao.countXxxxByXxx(params); if( nums > 0 ){ //当存在时,执行这里 }else{ //当不存在时,执行这里 }
2.问题分析
采用上述SQL语句,即会去查询所有满足 where 条件的记录。而我们的需求只是判断是否存在满足where的记录,因此查询到一条又继续查找其它满足条件的记录是完全没有必要的。这对数据库的性能也会造成一定影响。
3.优化方案
优化方案:改用 LIMIT 1
,让数据库查询时遇到一条就返回,不要再继续查找还有多少条了。
select 1 from the_table_name where ... limit 1
业务代码中直接判断是否非空即可:
/* 解释为什么是判断非空: 我们优化后的SQL语句:select 1 ... limit 1 至多查询一条记录 - 如果查询到了,那么返回 1,可以用Integer接收 - 如果没有查询到,那么就是返回 null, 这也是为什么我们的 isExist 不能是int类型的原因 不能用基元类型去接收 null 而对于我们最开始提到的普遍SQL语句,为什么能用int接收呢? 因为 select count(*) 的查询结果一定是一个 >= 0 的整数 因此在 应用层(Java端)接收到的一定是一个整数,不会出现接收 null 的情况 */ Integer isExist = xxDao.countXxxxByXxx(params); if( isExist != NULL ){ //当存在时,执行这里 }else{ //当不存在时,执行这里 }
4.总结
根据查询条件查出来的条数越多,性能提升的越明显,在某些情况下,还可以减少联合索引的创建。
5.补充
5.1 还有什么时候可以使用LIMIT 1
针对的是会扫描全表的 SQL 语句,如果你可以确定结果集只有一条,那么加上LIMIT 1
的时候,当找到一条结果的时候就不会继续扫描了,这样会加快查询速度。
5.2 什么时候没必要使用LIMIT 1
如果数据表已经对字段建立了主键索引或唯一索引,那么可以通过索引进行查询,不会全表扫描的话,就不需要加上LIMIT 1
了。