【问题标题】:How to optimize MySQL query for large tables如何优化 MySQL 对大表的查询
【发布时间】:2014-02-10 03:10:55
【问题描述】:

我正在尝试优化以下查询,因为它需要很长时间才能执行。任何人都可以就如何优化这一点提供任何建议,并且他们可以推荐任何可以加快速度的索引。作为注释,eddata 表包含大约 100 万行,ddata 表包含大约 1500 万行。如果您运行查询,则从 ddata 中选择了大约 5,000 个项目

SELECT * FROM ddata WHERE DATE(startDate) = DATE(NOW());

我要优化的查询是:

SELECT e.ID,e.uID,e.sID
FROM edata e
LEFT JOIN ddata d ON e.sID=d.sID
WHERE DATE(d.startDate)=DATE(NOW());

谢谢

【问题讨论】:

  • 索引的基本经验法则:比较操作中使用的任何字段都应该有一个索引。这就是你的wherejoin 和有时order 子句中使用的任何东西。请注意,如果您在比较中使用从该字段派生的值,则在字段上设置索引没有任何用处,就像您使用 DATE() 调用一样。 startDate 可能会被索引,但像 md5(somefield) 这样的东西会强制进行表扫描。
  • 顺便说一句,使用 NOW() 意味着查询不会进入查询缓存——如果你用字符串预填充它,那么重复运行会更快。
  • 我会运行 EXPLAIN 语句 dev.mysql.com/doc/refman/5.0/en/explain.html 来向您显示有关查询的信息。您能否发布结果,以便我们给出相关答案。
  • 去掉LEFT JOIN,因为结果和INNER JOIN一样。你想达到什么目的?

标签: mysql sql optimization


【解决方案1】:

#1:您可能不想要外连接,因此将其替换为内连接(众所周知,MySQL 的优化器在确定外连接是否可以重写为内连接时很弱)。

#2:删除 d.startDate 上的函数。

SELECT e.ID,e.uID,e.sID
FROM edata e
JOIN ddata d ON e.sID=d.sID
WHERE d.startDate >= DATE(NOW())
AND d.StartDate < date_add(DATE(NOW(), interval 1 days);

【讨论】:

    【解决方案2】:

    专门针对这个查询,把where子句放在join之前,这样会大大减少执行时间。 其次,当您只选择左表的列时,为什么要使用 LEFT OUTER JOIN?这完全违背了 LEFT JOIN 的目的。所以一个简单的连接就可以了。

    SELECT e.ID,e.uID,e.sID
    FROM edata e,
        (select * from ddata
              WHERE DATE(startDate)=DATE(NOW()
        ) d
    WHERE e.sID=d.sID;
    

    一般来说,使用EXPLAIN statement 可以更好地理解和优化您的查询。如果您了解 DBMS 中的优化基础知识也会更好,这样您就可以应用索引等其他技术。

    【讨论】:

    • 加入 "d" 没有意义,因为它从不在选择列表中使用。
    • 但在join条件中使用。嵌套查询需要一个别名。所以是需要的。
    • "SELECT e.ID,e.uID,e.sID FROM edata e" 应该返回相同的结果
    • 那么ON e.sID=d.sID; 呢??
    • 这是一个 LEFT JOIN,这意味着即使没有匹配,外部表中的 所有 行也会返回。如果没有使用内部表中的列,您也可以简单地删除连接。大多数 RDBMS 会删除不必要的连接,但 MySQL 的优化器并不那么聪明。
    猜你喜欢
    • 1970-01-01
    • 2016-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-09
    • 1970-01-01
    • 2011-05-18
    相关资源
    最近更新 更多