武汉茑萝:MySQL中使用IN不会走索引分析以及解决办法

在MySQL中使用IN查询时,虽然理论上使用索引是为了提高查询效率,但是当IN中的值范围扩大时,索引可能会失效,导致一次扫描完表,从而降低查询速度。
这可以通过Navicat的解释功能在运行时信息中观察到。
当IN中的值只是主键时,查询类型(type)非常重要,比如system、const、eq_ref等,其中ref和const表示使用索引。
但是,当类型变为all或index时,则表明查询没有完全使用索引,可以进行全表扫描。
在这种情况下,必须对SQL进行优化。
如果Usingfilesort或Usingtemporary出现多余,则说明该索引完全没有使用,需要紧急调整。
随着IN的取值范围扩大,使用索引的效率下降,直到范围变得太大,导致索引失败,进入全表扫描。
此时,优化策略可能包括将IN查询转换为子查询或重新设计查询结构以减少索引扫描范围。
要解决MySQLIN查询慢的问题,首先要了解索引失败的原因,然后通过重建查询、使用临时表或内连接等方式将全表扫描转化为索引使用,从而提高查询性能。
例如,将原始IN查询转换为:原始SQL:SELECT*FROMtableWHEREcolumnIN(value1,value2,...)优化SQL:SELECT*FROMtableWHEREcolumnIN(SELECTcolumnFROMsub_tableWHEREcondition)通过此优化,查询速度可以显着提高。
具体效果可以通过对比优化前后的SQL执行速度信息来观察。

不要再问我in,exists走不走索引了...

前言在处理业务需求时,我们面临着将一条数据A存储到数据库B中,并发现数据库B的附加部分。
为了简化问题,我用一个模型来描述这个过程。
当我们探索解决方案时,我们发现了类似于“notin”和“notexists”的逻辑。
然而,我们对“IN”、“NOTIN”、“EXISTS”和“NOTEXISTS”四个运算符的用法和有效性以及它们是否真的不使用索引存有疑问。
带着这些问题,本文将一一解答。
使用说明为了方便理解,我们创建了两个表t1和t2,并输入了一些数据。
其中id为主键,name为普通索引。
对于当前问题,我们可以使用“NOTIN”或“NOTEXISTS”来过滤表t1中大于表t2的数据。
对name字段进行匹配操作。
执行结果是一样的,但请注意“NOTIN”和“NOTEXISTS”的使用有差异。
“NOTIN”要求子查询中对应的字段不为空,否则可能返回空结果。
在表t2中添加具有空值的名称后,“NOTIN”将返回一个空集。
“NOTEXISTS”返回一个布尔值,不关心返回的具体数据。
在执行效率方面,根据MySQL版本的不同,“IN”和“EXISTS”索引的使用存在差异。
“IN”和“EXISTS”的有效性取决于相应字段的长度和数据量,并且存在一定的临界点。
执行流程in,exists当执行“IN”查询时,MySQL会先执行子查询得到结果集,然后与外部表进行笛卡尔积运算,过滤出满足条件的数据。
“EXISTS”查询首先遍历外表并确定内表中每条记录的匹配方式。
只有在内表中找到匹配项时才会返回true。
暗示?网上有一种说法是“IN”和“EXISTS”不会被索引,但事实并非如此。
根据MySQL版本和字段长度的不同,是否使用索引存在差异。
通过实际测试验证,可以发现数据量和字段长度相关的规律。
效果如何?对于网上流传的“EXISTS”比“IN”更有效的说法,经数据量测试发现实际情况并不相符。
在不同数据量的情况下,“IN”和“EXISTS”的执行效率是不同的,不同情况下优化器的处理也存在差异。
哪个更快或更慢,不存在还是不存在?对于“NOTIN”和“NOTEXISTS”的对比,测试结果表明,在不同数据量和索引类型的情况下,执行效率存在差异。
一般来说,当小表用作外部表时,“NOTEXISTS”效率更高,而当大表用作外部表时,“NOTIN”与“NOTEXISTS”一样高效,或者“NOTIN”更快。
嵌套JOIN循环为了理解为什么“IN”被转换为JOIN,有必要了解JOIN嵌套循环的三个连接。
包括循环连接简单嵌套循环连接、嵌套索引循环连接和嵌套块索引连接。
这三种连接方式在复杂度和效率上存在差异。
使用索引和缓存优化可以显着提高执行效率。