现在网上对于in的讨论、比较有很多,我认为最严谨的说法就是慎用。但是慎用不代表不要用,in的存在也有存在的理由,因为in有自己的应用场景。要使用in需要了解in在MySQL优化器中如果和转化的。例如有一张表A中有C1、C2、C3、C4、c5。where C1 IN (‘c1value1’,’c1value2’) AND C2 IN(‘c2value1’,’c2value2’);在这个情况下,MySQL优化器会转化成2*2=4种组合。对于4种组合这种情况来说是相对理想的,但是有一点组合越大,性能越差。
很多情况下可以通过其他查询来替代in查询。如果没有索引或者单列索引对于值的比较,用between and或者>或者<比较合适,因为在MySQL对值进行比较的时候只比较一次。而in的话会被比较多次。如果in子查询性能很多时候也不是很理想。MySQL优化器改写的sql执行效率很多情况下都是很糟糕的。关于子查询再后续的文章中在做讨论。那么什么情况下适合使用in呢。我认为覆盖索引非最后一列字段且该字段的查询条件是多个值的可以考虑使用in,因为索引有最左原则。以表A为例子,如果查询表A中c2,c3列,其中c3=’c3value’ ,c4值c4value1、c4value2、c4value3、
c5=’c5value5’,另外index idx_c3_c4_c5(索引的顺序依次是C3,C4,C5)。要完成这个查询查询的sql有很多种,一般情况下,我认为性能较好的sql应该是select c2,c3 from a where c3=’c3value’ and c4 in (c4value1、c4value2、c4value3) and c5=’c5value5’。因为c4位于索引的第二列,如果使用between and 、>、<这些范围查询查询,一定程度上,能够提升性能(相对于全表扫描来说,或者index_c3),但这不是最好的选择,因为无法利用index_c3_c4_c5中的c5列,这里使用in,优化器会转化成三种集合,可以充分利用index_c3_c4_c5中的所有列。如果遇到查询c1,c2列查询条件是c4=c4value1 and c5=c5value,如果c3的值个数有限,这里以性别为例,c3列存储都是男或者女,那么sql可以写成select c1,c2 from A where c3 in(‘男’,’女’) and c4=c4value1 and c5=c5value,但是这种技巧不能滥用。
然而sql是不是最好的选择还要看MySQL的执行计划。因为MySQL内部有一个统计引擎,在数据分布比较极端的情况下,查询出来的数据中随机I/O比全盘扫描锁消耗的时间还要长,那么以上的就不一定是最好的。