【问题标题】:Indexing on JOIN and WHERE clauses对 JOIN 和 WHERE 子句进行索引
【发布时间】:2017-05-13 05:09:24
【问题描述】:

如果我的查询看起来像:

SELECT *
FROM member
LEFT JOIN group ON (member.group_id = group.id)
WHERE group.created > @date
ORDER BY member.last_updated 

如果我为以下各项创建两个索引:

member.group_id, member.last_updated
group.id, group.created

这是优化原始查询的最佳方法吗?我应该添加一个新字段member.group_created 并像这样索引:

member.group_created, member.last_updated

【问题讨论】:

  • 我建议使用 EXPLAIN 语句 dev.mysql.com/doc/refman/5.7/en/explain.html 检查这两种情况,然后查看。
  • 我敢打赌,添加 member.group_created 将没有多大用处,也不会加快您的查询速度。为方便起见,您正在打破 3NF。优化器将正确使用 group.created 上的索引。如果您打算做任何事情来加快速度,请测试在 member.last_updated 上添加非聚集索引
  • 只需创建两个单独的索引-->1.member.group_id 2.group.created,我认为'group'表中的'id'将是主键,不需要索引,因为primarys会默认在mysql中索引
  • 很好,我可以从第二个索引中排除group.id,但这并不能解决member.last_updated对结果排序的优化问题。也许这不是必需的,因为我们将扫描与member 匹配的所有结果,因此索引不会大幅提高性能?但是,如果这是我们有兴趣通过member.group_id 查询的唯一查询,那么将member.last_updated 添加到索引中的开销是最小的,不是吗?
  • 请注意,group 是一个保留字,因此对于表标识符来说不是理想的选择

标签: mysql join indexing


【解决方案1】:
SELECT  *
    FROM  member AS m
    LEFT JOIN  group AS g  ON (m.group_id = g.id)
    WHERE  g.created > @date
    ORDER BY  m.last_updated 
  • 如果您不需要所有 (*) 两个表的列,请不要要求它们;它可能会影响性能。
  • 你真的需要LEFT吗?也就是说,您是否希望 NULL 用于“右”表中缺少的任何行?
  • 如果优化器决定从member 开始,它可能会从INDEX(last_updated) 中受益。假设idPRIMARY KEY ofgroup`,则不需要额外的索引。
  • 如果它决定以group 开头,那么INDEX(created) 可能有用。那么m需要INDEX(group_id)

所以,添加我建议的 3 个索引,如果它们不存在的话。

如果您有更多问题,请提供SHOW CREATE TABLEEXPLAIN SELECT ...

【讨论】:

    【解决方案2】:

    不要在左连接表上使用 where 子句,而是这样做。

    选择 * 来自会员

    LEFT JOIN group ON (member.group_id = group.id and group.created > @date)

    ORDER BY member.last_updated

    还在组表中添加索引(id,created)

    【讨论】:

    • 请保留ON 以说明这些表之间的关系。然后在WHERE 中有过滤子句。
    • 你是对的,但是你不能在左连接上放置过滤器,因为它会降低性能,在内部连接中你可以这样做
    • 如果结果集相同,那么优化器将“做正确的事”。如果结果集不同,谁在乎性能。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多