场景

A 表中大约有 50 万行数据,其中有一个 a 字段,其上未加索引,不同的 a 有大约 3000 个。

要求

指定了 250 个 a ,要求判断其中多少个在 A 表中出现过。

第一版 SQL

1
2
3
SELECT DISTINCT a
FROM `A`
WHERE a IN (250个指定 a)

执行速度约 40秒

第二版 SQL

1
2
3
4
SELECT * FROM
(SELECT DISTINCT a
FROM `A`) AS t
WHERE t.a IN (250个指定 a)

执行速度约 0.7秒

分析原因

  1. 因为 a 上未加索引,直接 where 条件 in 的话会对 50 万行原始数据依次比较是否在 250 个指定 a 中,比较次数为 50万*250 = 1.25 亿次
  2. 如果先 distinct 全部,再子查询 in,只会在 distinct 的 3000 个结果中依次比较 250 个指定 a,比较次数为 50万+3000*250 = 80 万次

结论

在未加索引的字段上面进行大量 in 操作,使用子查询先预筛选,可以达到近似索引的效果。