【问题标题】:MySQL NOT IN taking foreverMySQL 不会永远占用
【发布时间】:2011-11-29 15:59:31
【问题描述】:

此查询过去需要 4 到 5 秒才能运行。这是我的表格统计信息:

学生表:4200 行

idtrack 表 15000 行

这是我的查询:

SELECT students.student_id
FROM students
WHERE students.grade_level ='12' 
AND students.student_id 
NOT IN (
    SELECT idtrack.student_id
    FROM idtrack
    WHERE idtrack.event_id ='33'
)

现在完成此查询需要 30 秒。有人可以帮我优化/重构吗?提前致谢。

【问题讨论】:

  • 子查询总是需要时间,确保有索引并查看查询的执行计划
  • 如果您发布您的表格架构,那就更好了。

标签: php mysql sql subquery


【解决方案1】:

你也可以试试

SELECT students.student_id
FROM students
LEFT JOIN idtrack ON idtrack.event_id='33' AND idtrack.student_id = students.student_id
WHERE students.grade_level ='12' 
AND idtrack.student_id IS NULL

【讨论】:

  • 我试过这个,但仍然收到缓慢的结果。我最终用 PHP 和数组 intesect 来做这件事!谢谢!
【解决方案2】:

也许您忘记为表格创建主键?

【讨论】:

  • 我有所有表的主键。
  • 最好在绑定字段上创建索引students.student_ididtrack.event_id
【解决方案3】:

EXISTS 通常要快得多,因为在您的情况下,它允许 MySQL 在发现 idtrack 中与 NOT EXISTS 子句相矛盾的记录时短路。

SELECT students.student_id
FROM students
WHERE students.grade_level ='12' 
AND NOT EXISTS (
SELECT idtrack.student_id
FROM idtrack
WHERE idtrack.event_id ='33'
AND idtrack.student_id = students.student_id
)

【讨论】:

  • 唯一索引字段的比率为 4:1?我会感到非常惊讶。
  • @symcbean:我没有注意到每个表的记录数。
【解决方案4】:

如何在 idtrack 上加入学生,并过滤“where students.grade_level=12 and idtrack.event_id 33”?连接应该比子查询快。简单的等式/不等式比“不在”快得多

【讨论】:

    【解决方案5】:

    没有看到创建表命令和解释输出是相当困难的。但你可以试试:

    SELECT students.student_id
    FROM students LEFT JOIN idtrack
        ON students.id=idtrack.student_id
        AND idtrack.event_id ='33'
    WHERE students.grade_level ='12' 
    AND idtrack.student_id IS NULL
    

    顺便说一句,如果 idtrack.event_id 和 students.grade_level 被声明为数字,那么它们不应该被引用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-07-23
      • 2014-11-07
      • 1970-01-01
      • 2020-11-18
      • 1970-01-01
      • 1970-01-01
      • 2021-04-15
      • 2014-11-01
      相关资源
      最近更新 更多