【MySQL-索引调优】12:In的使用

【MySQL-索引调优】12:In的使用 1-InSELECT*FROMordersWHEREuser_idIN(1,2,3);# 本质等价SELECT*FROMordersWHEREuser_id1ORuser_id2ORuser_id3MySQL优化器通常会把IN转换为多次等值匹配范围扫描 / index lookup所以本质也可以走索引(type: range)但是要注意in内部如果过多性能就会爆炸此时可能会被切换成全表扫描2-Not In执行SELECT*FROMordersWHEREuser_idNOTIN(1,2,NULL);# 本质等价SELECT*FROMordersWHEREuser_id!1ANDuser_id!2ANDuser_id!NULL会发现一条都查不出来在SQL比较中存在TRUE、FALSE、UNKNOWN未知三种状态任何值和NULL比较 → 结果都是UNKNOWNWHERE只保留TRUEFALSE 和 UNKNOWN 都会被过滤掉user_idIN(1,2,NULL)# 等价于user_id1ORuser_id2ORuser_idNULL# 假设某一行user_id3# 去比较三个条件会变成3!1→TRUE3!2→TRUE3!NULL→ UNKNOWN# 会变成TRUEANDTRUEANDUNKNOWN → UNKNOWN# 所以后续每一行都是UNKNOWNwhere直接过滤了# 所以user_id 3这一行就没了后续每一行都是这样所以一条都查不出来所以使用NOT IN(...)一定要注意这个(...)中不要出现NULL3-NOT EXISTS由于NOT IN NULL这种查询天然的缺陷NOT IN 子查询所以一般会使用NOT EXISTS 子查询来规范化使用SELECT*FROMorders oWHERENOTEXISTS(SELECT1FROMusers uWHEREu.ido.user_id);当然强行使用NOT IN 子查询也可以但是记得子查询判空不要出现NULL的情况但是不规范建议少用PSNOT EXISTS是存在判断而NOT IN是值比较4-推荐写法小范围过滤WHEREuser_idIN(...)联合索引WHEREuser_id?ANDstatusIN(...)5-避免写法避免大 ININ(几千个)避免 NOT INNOTIN(...)替代子查询IN(SELECT...)→ 改JOIN