MySQL:in、exists、like、find_in_set 悠悠 2022-05-22 02:48 200阅读 0赞 坚持小表驱动大表的原则。 > 有人在争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][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优化的一个案例][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。 [max_allowed_packet]: https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_max_allowed_packet [MySQL NOT EXISTS]: https://blog.csdn.net/zyz511919766/article/details/49335647
还没有评论,来说两句吧...