在mysql中添加外键的成本是多少?

0 mysql index

我有一个应用程序,它有一个定义所有产品的 product_def 表。product_def 中的记录是固定的,永远不会被删除。

CREATE TABLE `product_def` (  
`product_id` INT( 5 ) UNSIGNED AUTO_INCREMENT ,
`product_name` VARCHAR( 20 ) DEFAULT NULL ,
PRIMARY KEY ( region_id ),
) AUTO_INCREMENT=1 ENGINE=innodb CHARACTER SET utf8 COLLATE utf8_general_ci   ;
Run Code Online (Sandbox Code Playgroud)

我有另一个 order_records 表,其中包含 5 个产品的记录。这个 order_records 表将是巨大的。我想知道我是否应该在 order_records 中使用外键来引用 product_def 表。考虑到数据大小和搜索或更新速度,在表中使用外键的成本是多少?我的情况是 product_def 表中的记录永远不会被删除,因此数据完整性不是这里的问题。

我的问题是:

(1) 假设 order_records 表有 10G 的记录,没有这 5 个外键。那么如果我向表中添加 5 个外键,order_records 会有多大?

(2) 添加5个外键后,在更新和从数据库中选择的性能差异是什么?
(表 order_records 将非常庞大。)

CREATE TABLE `order_records` (  
`order_id` BIGINT( 5 ) UNSIGNED AUTO_INCREMENT ,
`order_1_product_id` INT( 5 ) UNSIGNED  NOT NULL ,
`order_2_product_id` INT( 5 ) UNSIGNED  NOT NULL ,
`order_3_product_id` INT( 5 ) UNSIGNED  NOT NULL ,
`order_4_product_id` INT( 5 ) UNSIGNED  NOT NULL ,
`order_5_product_id` INT( 5 ) UNSIGNED  NOT NULL ,
`name` VARCHAR( 20 ) DEFAULT NULL ,
PRIMARY KEY ( order_id ),
FOREIGN KEY ( order_1_product_id ) REFERENCES product_def(product_id)  ON UPDATE CASCADE
   ???  use foreign key  ????
FOREIGN KEY ( order_5_product_id ) REFERENCES product_def(product_id)  ON UPDATE CASCADE
) AUTO_INCREMENT=1 ENGINE=innodb CHARACTER SET utf8 COLLATE utf8_general_ci   ;
Run Code Online (Sandbox Code Playgroud)

Bil*_*win 7

在 MySQL 中,外键需要索引。如果索引已经存在,外键将使用该索引(甚至使用现有多列索引的前缀)。如果不存在索引,则定义外键将构建索引。

因此,创建外键的大小增加和时间与在同一列上创建索引大致相同。

SELECT 的性能不会受到外键存在的显着影响。优化器只需要做一点额外的工作,就可以考虑新索引。

更新的性能更多,因为对于每个外键,一个INSERT/UPDATE/DELETE都要检查是否满足约束。这意味着对引用表的主键查找。这种影响是可以衡量的,如果引用的表不在缓冲池中,影响会更大。

另一个影响是锁定。如果我更新具有外键的子行中的一行,InnoDB 会在父表中引用的行上放置一个共享锁。这意味着在我提交之前没有人可以更新这些父行。如果您有很多线程更新子行,那么父行可能在大部分时间都被锁定,这会导致很难在父表中进行并发工作。与其说是性能问题,不如说是并发问题。

与所有“表现如何”问题一样,答案实际上取决于您的工作量。例如,如果您没有并发更新,则该问题可能不会影响您的所有实际用途。用负载测试自己测试它是唯一确定的方法。StackOverflow 上的任何人都无法准确地为您解答。