【问题标题】:Mysql forces me to create several indexes in case of multiple-column unique key在多列唯一键的情况下,Mysql 强制我创建多个索引
【发布时间】:2015-11-03 10:03:02
【问题描述】:

在以下示例中:

table1 (id, f1, f2)

table2 (id, f3, f4)

related_table(id, table1_id, table2_id)

我有 2 个表和一个具有 HasAndBelongToMany 关系的相关表。(注意到我使用的结构适用于 ORM)。

当我使用两个外键创建多列索引时出现问题:

CREATE UNIQUE INDEX i1
ON related_table (table1_id, table2_id)

然后,我可以添加 table1_id 关系,但我不能添加 table2_id 关系。 Mysql 说我没有 table2_id 列的任何索引。这是为什么呢?

假设如果你创建一个多列索引,使用这个索引你可以通过两个字段中的任何一个进行搜索。

【问题讨论】:

  • 你能把你的table1、table2和相关表的表信息也发布一下吗?您是否有一些引用 table1 和 table2 的外键约束?

标签: mysql indexing


【解决方案1】:

这是mysql使用索引的结果。在multiple-column indexes 上的 mysql 文档中清楚地记录了这一点:

MySQL 可以将多列索引用于测试索引中所有列的查询,或者只测试第一列、前两列、前三列等的查询。如果您在索引定义中以正确的顺序指定列,则单个复合索引可以加快对同一张表的多种查询。

外键关系需要该字段的索引。对于 table1_id,您可以使用多列索引,因为 table1_id 是最左边的字段。对于 table2_id 你不能使用多列索引,因为它不是最左边的字段。因此,很遗憾,如果您想在 2 个表之间正式创建关系,则需要在 table2_id 上创建单独的索引。

【讨论】:

    【解决方案2】:

    要对table2_id 有用,您需要一个以该列开头的索引。

    想象一个电话簿。这基本上是“last_name,first_name”的索引。按名字查找人并不是那么有用。

    【讨论】:

    • “按名字查找人并不是那么有用。”看完整部电话簿还是比挨家挨户走遍城里所有房子要好,还要O(n)
    【解决方案3】:

    这是多对多关系表的最佳模式:

    CREATE TABLE t1_t2 (
        t1_id ... NOT NULL,
        t2_id ... NOT NULL,
        PRIMARY KEY(t1_id, t2_id),
        INDEX      (t2_id, t1_id)  -- This is what you were missing.
    ) ENGINE=InnoDB;
    

    另见further details

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-05-11
      • 2017-02-28
      • 1970-01-01
      • 2010-12-07
      • 2017-01-20
      • 1970-01-01
      • 2017-02-01
      相关资源
      最近更新 更多