4

我有一个带有单个唯一 VARCHAR(512) 字段的表。我想让另一个表保存对第一个表的外键引用。两个表都使用 InnoDB。如果我向第二个表添加一个 VARCHAR(512) 键并在其上添加一个外键约束,那么 512 字节长的数据会被保存两次吗?

如果是这样,有没有办法只保留对索引的引用而不是对 varchar 本身的引用?

简而言之,我的问题是,在 InnoDB 中是否有一种有效的方法来保存长 VARCHAR 字段的外键?

非常感谢,

亚尼夫

4

3 回答 3

3

我进行了一个简单的测试:创建 3 个表,一个用于保存数据本身,包含两列,ID (int) 和数据 (varchar[120]),另一个使用 ID 作为外键的表,最后一个使用数据作为外键:

CREATE TABLE `dados` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(120) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `name` (`name`) USING BTREE,
  KEY `idx` (`id`,`name`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

CREATE TABLE `refINT` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `dado` int(10) unsigned NOT NULL,
  PRIMARY KEY (`id`),
  KEY `id` (`dado`),
  CONSTRAINT `id` FOREIGN KEY (`dado`) REFERENCES `dados` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

CREATE TABLE `refSTR` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `dado` varchar(120) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
  PRIMARY KEY (`id`),
  KEY `nome` (`dado`),
  CONSTRAINT `nome` FOREIGN KEY (`dado`) REFERENCES `dados` (`name`) ON DELETE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;

在每个表中插入 100 条记录并比较最终的表大小:

dados:  192.0 KB
refINT: 32.0 KB
refSTR: 32.0 KB

所以我猜数据不会在 varchar 外键中复制,至少在 MySQL 5.1 版本中是这样。

于 2011-04-23T22:42:25.017 回答
2

是的,如果VARCHAR(512)引用表上有列,则数据将存在两次。

我建议您让引用表的外键引用第一个表的整数主键,而不是 512 字节数据。这就是标准化的全部内容。

于 2009-08-16T21:50:35.380 回答
0

保持较小的密钥大小总是好的。您可以VARCHAR通过在插入时生成一个额外的校验和列来解决索引大的问题。此校验和字段将包含散列算法的输出,CRC32()或者可能MD5()包含较大列的输出。

于 2011-04-23T22:47:47.087 回答