带有 IN 子句的 SQL 查询的 MYSQL 查询优化

Posted

技术标签:

【中文标题】带有 IN 子句的 SQL 查询的 MYSQL 查询优化【英文标题】:MYSQL query optimization for SQL query with IN clause 【发布时间】:2016-04-26 10:21:47 【问题描述】:

我有以下 SQL 查询,我根据用户输入动态构建。只要 IN 参数

我曾尝试在输入较少的多个查询中拆分查询并并行触发所有查询。这肯定会给我更好的性能

但是我想避免拆分查询,想知道是否有任何其他(更好的)方法可以进一步优化此查询(我正在考虑是否可以通过创建临时表来使用连接)

[请注意 col1 & col2 已经是一个索引]

SELECT a.col3, b.col5, b.col4, ...
FROM A a 
  JOIN B b ON a.apk = b.afk AND a.bfk = b.bpk  
WHERE a.col1 IN (1, 2, 3, ...)  
  AND a.col2 IN ('abc', 'pqr', ...) 
  AND a.flag = 1 

【问题讨论】:

用这些参数创建一个临时表并加入它 ON a.apk = b.afk AND a.bfk = b.bpk....当您基于 2 个不同的列加入两个表时是否正确... 至少,关于查询性能的问题总是需要针对所有相关表的正确 CREATE 语句和 EXPLAIN 的结果。 【参考方案1】:

mysql 在处理带有常量的IN 查询方面做得很好。与许多其他数据库不同,它实际上对输入进行排序并使用二叉​​树进行搜索。所以,我的猜测是数据量是问题而不是IN 本身。并行线程工作得更好这一事实说明 MySQL 不会将所有可用资源用于单个查询。

您可以尝试索引。对于这个查询:

SELECT a.col3, b.col5, b.col4, ...
FROM A a JOIN
     B b
     ON a.apk = b.afk AND a.bfk = b.bpk  
WHERE a.col1 IN (1, 2, 3, ...) AND
      a.col2 IN ('abc', 'pqr', ...) AND
      a.flag = 1 ;

您希望在b(fk, bpk)a(flag, col1, col2)a(flag, col2, col1) 上建立索引。多列索引可以帮助IN,但仅限于其中之一,因此更具选择性的应该是索引中的第二列。

【讨论】:

以上是关于带有 IN 子句的 SQL 查询的 MYSQL 查询优化的主要内容,如果未能解决你的问题,请参考以下文章

使用带有休眠 SQL 查询的多列的参数化 IN 子句

将数组转换为 WHERE IN mysql 子句的格式

MySQL 高级SQL操作(数据的增删改查)

MySQL 不使用带有 WHERE IN 子句的索引?

mysql分页查询

JPA - 带有in子句和不区分大小写的规范