【问题标题】:Does using Identifying Many-To-One Relationship means having to have duplicate PRIMARY and FOREIGN keys on same table?使用识别多对一关系是否意味着必须在同一张表上有重复的 PRIMARY 和 FOREIGN 键?
【发布时间】:2019-01-03 12:28:15
【问题描述】:

原标题:当 PRIMARY KEY 和外键 INDEX 设置在同一个列名上,是不是意味着同一个索引是重复的?

例子:

我使用 MySQL Workbench 生成了一个表,并使用识别与其他表的关系。这意味着 PRIMARY KEY 在我的例子中包含 FOREIGN KEY 列。

CREATE TABLE IF NOT EXISTS `price_history` (
`amount` DECIMAL NULL,
  `date_start` DATE NULL,
  `date_end` DATE NULL,
  `product_id` INT NOT NULL,
  `category_id` INT NOT NULL,
  `priceitem_id` INT NOT NULL,
  PRIMARY KEY (`product_id`, `category_id`, `priceitem_id`),
  INDEX `fk_idx` (`product_id` ASC, `category_id` ASC, `priceitem_id` ASC),
ENGINE = InnoDB;

我注意到PRIMARY KEYINDEX 定义了相同的列。这是否意味着我将在桌面上有两个单独的“物理”索引?会不会很浪费?

我想知道识别关系是否是必要的罪恶。

【问题讨论】:

  • 索引基本上是多余的。除了特定的asc 排序之外,它们都是骗子,所以你基本上是在添加/更改/删除记录时数据库必须做的工作加倍。
  • 我可以(而且我确实)在主键索引内的表上有一个 id 字段。我删除了它以强调重复。换句话说,虽然.. 识别关系通常会产生这种重复,使工作加倍。我觉得这很令人费解。
  • 您可以在一个字段上拥有任意数量的索引,可以是单字段索引,也可以是复合索引。它会造成的唯一危害是必须维护它们的额外开销。 如果从不必须进行查询,您可能只使用索引中的某些字段,例如where category_id=... and priceitem_id=...,然后随意做一个复合键。但是,如果您确实需要以任何部分组合访问这些字段,那么您最好在字段上使用单独的索引。最好在字段上有单独的索引,而不是多个重叠的索引。
  • 当然,如果您需要在这些字段上创建unique 索引,那么您确实需要有一个复合键来强制元组的唯一性。单独的唯一索引不起作用,因为 (1,2)(1,3) 将是唯一的元组,但是使组件单独唯一会触发 1 值的重复键违规。
  • 在我的具体情况下,我确实需要对三元组的 unique 约束。我不需要将它放在主键中。然而,令我惊讶的是,如果我要建立识别关系,这些列也会全部进入primary key,这就是我开始问自己“我真的想要识别关系”的地方,即使它使从概念上讲......除了重复索引之外,识别关系似乎不会在这里添加任何东西

标签: mysql duplicates foreign-keys composite-primary-key


【解决方案1】:

如果我理解您的问题,我认为不会发生这种情况。在下面,price_history 没有数据库引擎自动创建的重复索引。

create table A
(   `product_id` INT NOT NULL,
    `category_id` INT NOT NULL,
    `priceitem_id` INT NOT NULL,
    PRIMARY KEY (`product_id`, `category_id`, `priceitem_id`)

)ENGINE=INNODB;

CREATE TABLE IF NOT EXISTS `price_history` (
    `amount` DECIMAL NULL,
    `date_start` DATE NULL,
    `date_end` DATE NULL,
    `product_id` INT NOT NULL,
    `category_id` INT NOT NULL,
    `priceitem_id` INT NOT NULL,
    PRIMARY KEY (`product_id`, `category_id`, `priceitem_id`),
    FOREIGN KEY `f` (`product_id`, `category_id`, `priceitem_id`) references A(`product_id`, `category_id`, `priceitem_id`)
)ENGINE = InnoDB;

show create table price_history;
CREATE TABLE `price_history` (
   `amount` decimal(10,0) DEFAULT NULL,
   `date_start` date DEFAULT NULL,
   `date_end` date DEFAULT NULL,
   `product_id` int(11) NOT NULL,
   `category_id` int(11) NOT NULL,
   `priceitem_id` int(11) NOT NULL,
   PRIMARY KEY (`product_id`,`category_id`,`priceitem_id`),
   CONSTRAINT `price_history_ibfk_1` FOREIGN KEY (`product_id`, `category_id`, `priceitem_id`) 
      REFERENCES `a` (`product_id`, `category_id`, `priceitem_id`)
 ) ENGINE=InnoDB;

 CREATE TABLE IF NOT EXISTS `price_history` (
    `amount` DECIMAL NULL,
    `date_start` DATE NULL,
    `date_end` DATE NULL,
    `product_id` INT NOT NULL,
    `category_id` INT NOT NULL,
    `priceitem_id` INT NOT NULL,
    PRIMARY KEY (`product_id`, `category_id`, `priceitem_id`),
    FOREIGN KEY `f` (`product_id`, `category_id`, `priceitem_id`) references A(`product_id`, `category_id`, `priceitem_id`)
)ENGINE = InnoDB;

show create table A;
CREATE TABLE `a` (
   `product_id` int(11) NOT NULL,
   `category_id` int(11) NOT NULL,
   `priceitem_id` int(11) NOT NULL,
   PRIMARY KEY (`product_id`,`category_id`,`priceitem_id`)
 ) ENGINE=InnoDB;

 CREATE TABLE IF NOT EXISTS `price_historyBBB` (
    id int auto_increment primary key,
    `amount` DECIMAL NULL,
    `date_start` DATE NULL,
    `date_end` DATE NULL,
    `product_id` INT NOT NULL,
    `category_id` INT NOT NULL,
    `priceitem_id` INT NOT NULL,
    FOREIGN KEY `g` (`product_id`, `category_id`, `priceitem_id`) references A(`product_id`, `category_id`, `priceitem_id`)
)ENGINE = InnoDB;

show create table price_historyBBB;
CREATE TABLE `price_historybbb` (
   `id` int(11) NOT NULL AUTO_INCREMENT,
   `amount` decimal(10,0) DEFAULT NULL,
   `date_start` date DEFAULT NULL,
   `date_end` date DEFAULT NULL,
   `product_id` int(11) NOT NULL,
   `category_id` int(11) NOT NULL,
   `priceitem_id` int(11) NOT NULL,
   PRIMARY KEY (`id`),
   KEY `g` (`product_id`,`category_id`,`priceitem_id`),
   CONSTRAINT `price_historybbb_ibfk_1` FOREIGN KEY (`product_id`, `category_id`, `priceitem_id`) 
      REFERENCES `a` (`product_id`, `category_id`, `priceitem_id`)
 ) ENGINE=InnoDB;

show indexes from price_history;
show indexes from price_historyBBB;

因此,如果存在足够的键(例如,复合)最左边的块足以重用,那么 db 引擎将不会自动创建 Helper 索引。

例如,如果您有一个由 (col1,col2,col3,col5) 组合而成的键(PK 或其他),并且您的 FK 要求使用 (col1,col2),那么新索引不是自动生成。

如果需要 FK 是为了 (colX,col1,col2) 那么上面的 (col1,col2,col3,col5) 没有用(最左边的优先级)并且 db 引擎将需要创建一个 FK 助手索引。

【讨论】:

    猜你喜欢
    • 2013-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-10
    相关资源
    最近更新 更多