使用 IN 子句和子查询进行极端查询优化

Posted

技术标签:

【中文标题】使用 IN 子句和子查询进行极端查询优化【英文标题】:Extreme query optimization with IN clause and subquery 【发布时间】:2015-02-25 15:00:57 【问题描述】:

我的表刚才有超过 1500 万行。 我需要运行这样的查询:

SELECT ch1.* FROM citizens_dynamic ch1
WHERE ch1.id IN (4369943, ..., 4383420, 4383700)
AND ch1.update_id_to = (
    SELECT MAX(ch2.update_id_to)
    FROM citizens_dynamic ch2
    WHERE ch1.id = ch2.id AND ch2.update_id_to < 812
)

基本上,对于IN 子句中的每个公民,它都会搜索最接近但低于指定update_id_to 的行。

在 2 列 update_id_to, id 上有 PRIMARY 键。 目前,此查询在 0.9 秒内执行(IN 子句中有 100 个 id)。 它仍然太慢,我需要运行我的脚本 3 天才能完成。

您可以在下面看到我的EXPLAIN 输出。

id 索引与 PRIMARY 键类似,但列颠倒:id, update_id_to

你有什么想法可以让它更快吗?

【问题讨论】:

【参考方案1】:

我发现 mysql 在使用 JOIN 时往往比关联子查询表现更好。

SELECT ch1.*
FROM citizens_dynamic AS ch1
JOIN (SELECT id, MAX(update_id_to) AS update_id_to
      FROM citizens_dynamic
      WHERE id IN (4369943, ..., 4383420, 4383700)
      GROUP BY id) AS ch2
    ON ch1.id = ch2.id
WHERE ch1.id IN (4369943, ..., 4383420, 4383700)

另外,请参阅此问题中的其他方法:

Retrieving the last record in each group

【讨论】:

以上是关于使用 IN 子句和子查询进行极端查询优化的主要内容,如果未能解决你的问题,请参考以下文章

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

慢查询问题常见的优化方法

在 IN 子句中使用硬编码值和子查询

删除“NOT IN”子句并优化查询

IN vs NOT EXISTS 子句,查询优化

MySQL大数据量分页查询方法及其优化