MySQL是否隐式生成UNIQUE和FOREIGN KEY约束的索引,还是应该实际创建它们?

时间:2016-09-26 09:59:43

标签: mysql sql database-performance

让我们考虑一个包含2个简单表的数据库:tablea具有INT id,VARCHAR something字段和引用tableb(包含相同字段但具有UNIQUE约束添加)。

如果我们使用它来设计和转发设计这个模式,MySQL Workbench将生成以下代码:

CREATE TABLE IF NOT EXISTS `tableb` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `something` VARCHAR(45) NULL,
  PRIMARY KEY (`id`),
  UNIQUE INDEX `something_UNIQUE` (`something` ASC))
ENGINE = InnoDB;

CREATE TABLE IF NOT EXISTS `tablea` (
  `id` INT NOT NULL,
  `something` VARCHAR(45) NULL,
  `tableb_id` INT NOT NULL,
  PRIMARY KEY (`id`, `tableb_id`),
  INDEX `fk_tablea_tableb_idx` (`tableb_id` ASC),
  CONSTRAINT `fk_tablea_tableb`
    FOREIGN KEY (`tableb_id`)
    REFERENCES `tableb` (`id`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB;

但我们似乎可以通过更简单,简约的代码达到相同的效果(表,列和约束的相同模式):

CREATE TABLE IF NOT EXISTS `tableb` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `something` VARCHAR(45) NULL,
  PRIMARY KEY (`id`),
  UNIQUE (`something`)
) ENGINE = InnoDB;

CREATE TABLE IF NOT EXISTS `tablea` (
  `id` INT NOT NULL,
  `something` VARCHAR(45) NULL,
  `tableb_id` INT NOT NULL,
  PRIMARY KEY (`id`, `tableb_id`),
  FOREIGN KEY (`tableb_id`) REFERENCES `tableb`(`id`)
) ENGINE = InnoDB;

第一个版本是否比第二个更好(例如更快)? MySQL也不会在第二种情况下创建第一版中提到的索引吗?

1 个答案:

答案 0 :(得分:0)

在我在评论中提到的最后一个块中,如手册所述,您不需要在子表(引用)中显式创建与FK相关的键。如果需要,MySQL会根据最左边的情况自动为你创建它们(或者首先是手册中所说的)。单列索引自然是最左边的。对于复合材料,即多列密钥,最左边自然是有道理的。

如果您运行上述内容并发出

,那将非常明显
show create table tablea;

如果碰巧在孩子中已经定义了最左键,并且它可用于FK关系,则引擎将不会自己为您创建一个。

从标题为Using FOREIGN KEY Constraints的手册页

  

在引用表中,必须有一个索引所在的外键   列以相同顺序列为第一列。这样的   如果不是,则会自动在引用表上创建索引   存在。如果您创建,可能会稍后以静默方式删除此索引   另一个可用于强制执行外键约束的索引。   如果给定,则使用index_name,如前所述。

正如我在您的问题的评论部分中提到的那样,引用的表(父级)必须具有必要的最左侧密钥,以便在所有这些之前快速查找。该密钥不需要是PRIMARY或唯一密钥。但对于复合材料来说,它必须是最左边的。如果在孩子的ALTER TABLECREATE TABLE之前父母中没有一个,那么操作将失败

  

MySQL错误1215:无法添加外键约束

关于在子表中代表您(或不代表)创建密钥的几个简单示例:

  1. 如果您在col1上明确创建了一个密钥,并且它在FK中使用,则不会为您创建帮助密钥。

  2. 如果在(a,b,c,d)上明确创建复合键,并且(a,b)上有FK,则不会为您创建辅助键。

  3. 如果在(a,b,c,d)上显式创建复合键,并且(a,c)上有FK,则会为您创建一个辅助键。因为b会影响显式,并且需要新密钥。

  4. 如果在(a,b,c,d)上明确创建复合键,并且(a,b,c)上有FK,则不会为您创建辅助键。显式的最左边,以相同的顺序,足以满足FK的要求。