【问题标题】:Using index on join在连接时使用索引
【发布时间】:2010-07-17 10:39:22
【问题描述】:

对下面的查询使用 EXPLAIN

SELECT cha.cid AS cid,
       cha.data AS dl
FROM cha, c_users
WHERE uid = 808
AND cha.cid = c_users.cid;
  1. 它对cha 表进行全面扫描
  2. 使用来自c_users的多列索引(cid,uid)。

为什么不使用cha 的主键索引,而是进行全表扫描。有没有更好的方法来优化查询/表。

编辑: cha.cid 是我的主键。在下面的评论之后添加。

【问题讨论】:

  • cha.cid 是你的主键吗?
  • 是的 cha.cid 是主键
  • 我发现将其分成两个查询并创建适当的索引会更好

标签: sql mysql indexing


【解决方案1】:

在正常的 BTREE 中,以及 (cid,uid) 上的索引,如果您不指定 cid 并且仅搜索 uid,则需要进行扫描。 (uid,cid) 上的索引(注意顺序)会/可能会有所帮助。

这绝不是保证它会被使用,如果某个索引/连接很可能需要使用一定比例的索引,MySQL 可以猜测全扫描可能会更快(连续读取),和其他原因。您可以通过 FORCE INDEX 检查与扫描相比,使用密钥是否实际上更快(在测试之前禁用测试服务器上的查询缓存)。

【讨论】:

  • 与 BTREE 无关 - 覆盖索引需要按照定义的顺序匹配最左边的列。如果第一个不匹配,则不会考虑索引。
  • 我的错,将它与标准的 2 整数空间索引技巧 (RTREE) 混淆了,这当然与手头的问题无关,只是个人的脑残,仍然需要两者整数具有某种界限。为我辩护:这里已经很晚了;)
【解决方案2】:

为 uid 列创建索引。

当您询问有关性能的问题时,EXPLAIN 和 CREATE TABLE 语句的输出会使帮助者的事情变得更容易。请下次添加。

【讨论】:

  • 我已经描述了 EXPLAIN 的输出。您需要更多信息吗?
【解决方案3】:

由于cha 没有可用于此查询的covering index,它必须访问数据页以检索它需要的一些数据。根据表的统计,优化器决定先扫描索引再跳转到数据页的IO时间比只扫描表还要糟糕。

【讨论】:

    【解决方案4】:

    不会……

    SELECT cha.cid AS cid,
           cha.data AS dl
        FROM cha INNER JOIN c_users ON cha.cid = c_users.cid
        WHERE uid = 808;
    

    更惯用?

    (编辑考虑到 knittl 的评论)。

    【讨论】:

    • 语法是FROM table1 INNER JOIN table2 ON …,不带逗号
    猜你喜欢
    • 2017-11-25
    • 1970-01-01
    • 2018-11-18
    • 1970-01-01
    • 1970-01-01
    • 2017-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多