MySQL:in、exists、like、find_in_set

坚持小表驱动大表的原则。

有人在争exists查询与in查询的效率问题,这里得说以下,不同的mysql版本,不同的业务,不同的数据,执行效率是不一定的,这里涉及到了mysql优化器对sql语句的优化,子查询的数据量问题等等。
网上还有人说mysql5.6版本对in查询做了很好的优化,所以效率问题要看具体的场景,要看真实测试的数据来进行优化!

in

当B表的数据集必须小于A表的数据集时,in 优于 exists

-- 语法
SELECT * FROM A WHERE id IN (SELECT id FROM B);
SELECT * FROM A WHERE id NOT IN (11, '22', '2000-01-01');

-- in 列表项可以是数字、字符、日期、时间等类型,还能混合排列,无须和 column 类型保持一致
-- in 查询相当于多个 or 条件叠加:一个 in 只能对一个字段进行范围比对,如果要指定更多字段,可以使用 AND 或 OR 逻辑运算符
SELECT * FROM user WHERE uid IN(1,2) OR username IN('admin','manong');

1、先执行子查询(in 包含的语句)。然后将A表查询分为n次(n表示在子查询中返回的数据行数)。
SELECT * FROM A WHERE id=子查询结果1;
SELECT * FROM A WHERE id=子查询结果2;
......
2、Oracle中,in语句中可放的最大参数个数是1000个。mysql中,in语句中参数个数是不限制的。不过对整段sql语句的长度有了限制(max_allowed_packet 缺省值4M)。

exists

当A表的数据集小于B表的数据集时,exists 优于 in

SELECT * FROM A WHERE EXISTS(SELECT 1 FROM B WHERE B.id=A.id);

每次从A表中查出来一条数据,然后将结果里的 id 放在 exists 查询中执行。
子查询查到返回布尔值 true,没有查到返回布尔值 false。返回布尔值true则将该条数据保存下来,否则就舍弃掉。

MySQL NOT EXISTS优化的一个案例

like

like 广泛的模糊匹配,字符串中没有分隔符。

find_in_set(str, strlist)

find_in_set 精确匹配。
假如字符串str 在由N 子链组成的字符串列表strlist 中,则返回值的范围在 1 到 N 之间。
一个字符串列表就是一个由一些被‘,’符号分开的子链组成的字符串。

SELECT * FROM A WHERE FIND_IN_SET(name, '张三,李四,王五');
SELECT * FROM A WHERE FIND_IN_SET(name, '11,22,33');

name 要查询的字符串,strlist 字段名 参数以”,”分隔。
如果 name 不在 strlist 或 strlist 为空字符串,则返回值为 0 。如任意一个参数为NULL,则返回值为 NULL。这个函数在第一个参数包含一个逗号(‘,’)时将无法正常运行。

小结

1、如果待查询的条件是常量那就使用 IN,是变量则使用 FIND_IN_SET。
2、如果使用 IN 和 FIND_IN_SET 都能满足条件,则最好使用IN。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章