如何解决大量数据的 IN 子句 SQL 查询中的性能问题?

Posted

技术标签:

【中文标题】如何解决大量数据的 IN 子句 SQL 查询中的性能问题?【英文标题】:how to resolve preformance issue in IN Clause SQL Query for huge set of data? 【发布时间】:2020-08-30 18:15:34 【问题描述】:

我正在尝试从大量数据中进行查询。查询继续运行,没有任何结果或错误。我为一小组测试数据运行的相同查询工作正常。

查询:

> SELECT * FROM table1 t1 WHERE t1.col1 IN (SELECT distinct(t2.col2)
> FROM table2 t2 Left Join table3 t3 on t2.col1 = t3.col1  WHERE
> t3.col1=value);

我再次尝试使用

查询大量数据

SELECT * FROM table1 t1 WHERE t1.col1 = (raw_value); - 单值过滤器工作正常。

SELECT * FROM table1 t1 WHERE t1.col1 IN ( raw_value, raw_value); - 一个以上的值过滤器会导致性能问题。

请给我一些改进性能的建议。

-谢谢。

【问题讨论】:

您可以使用“EXPLAIN”来帮助您深入了解问题 - dev.mysql.com/doc/refman/5.7/en/explain.html。在表面上,我认为该列没有被索引? left join 的意义何在? 请提供SHOW CREATE TABLEEXPLAIN SELECT ... 请在代码问题中提供minimal reproducible example--包括剪切、粘贴和可运行代码。对于包含 DBMS 和 DDL 的 SQL,包括约束、索引和表格初始化。对于包括 EXPLAIN 结果和统计信息的 SQL 性能。请研究和总结。对于包括优化/性能基础的 SQL——立即导致索引、计划、统计和 SARGability。 Tips for asking a good SQL question 对于可以是文本的内容,请使用文本,而不是图像/链接。将您的问题所需的一切都放在您的帖子中,而不仅仅是在链接中。 【参考方案1】:

据我所知,不需要子查询中的left join,因为过滤器位于用于on 条件的同一列上:如果是这样,只需将其删除。我建议使用exists 来表达查询:

select t1.*
from table1 t1
where exists (select 1 from table2 t2 on t2.col2 = t1.col1 and t2.col1 = value)

为了提高性能,您需要在table2(col1, value) 上建立索引。 table1(col1) 上的索引也可能有所帮助。

【讨论】:

。 .您应该更清楚,不需要JOIN,因为过滤器位于用于ON 条件的同一列上。 @GordonLinoff:谢谢...更新了答案 - 用你自己的话!【参考方案2】:

大型 IN() 子句的性能总是很差 - 没有办法解决这个问题。解决方案是使用 JOIN 而不是 IN()。

更快的方法是:

SELECT    *
FROM      table1 t1
JOIN      table2 t2 ON t1.col1 = t2.col2
LEFT JOIN table3 t3 ON t2.col1 = t3.col1
WHERE     t2.col1=value;

另外,这里的LEFT JOIN实际上不会做任何事情,所以最佳形式是:

SELECT    *
FROM      table1 t1
JOIN      table2 t2 ON t1.col1 = t2.col2
WHERE     t2.col1=value;

确保你有一个索引

table2 (col1)
table2 (col2)

【讨论】:

以上是关于如何解决大量数据的 IN 子句 SQL 查询中的性能问题?的主要内容,如果未能解决你的问题,请参考以下文章

如何按 Oracle SQL IN() 子句中的值顺序对结果数据进行排序

将列表传递给 HQL 或 SQL 中的 IN 子句?

IN子句中的Spark sql限制

使用 .NET 中的类型化数据集将 SQL 参数传递给 IN() 子句

ORDER BY 子句“IN()”中指定的值,但在泛型 SQL 和 Informix 中

如何在使用变量的动态查询中指定 IN 子句?