我有一个带有单个唯一 VARCHAR(512) 字段的表。我想让另一个表保存对第一个表的外键引用。两个表都使用 InnoDB。如果我向第二个表添加一个 VARCHAR(512) 键并在其上添加一个外键约束,那么 512 字节长的数据会被保存两次吗?
如果是这样,有没有办法只保留对索引的引用而不是对 varchar 本身的引用?
简而言之,我的问题是,在 InnoDB 中是否有一种有效的方法来保存长 VARCHAR 字段的外键?
非常感谢,
亚尼夫
我有一个带有单个唯一 VARCHAR(512) 字段的表。我想让另一个表保存对第一个表的外键引用。两个表都使用 InnoDB。如果我向第二个表添加一个 VARCHAR(512) 键并在其上添加一个外键约束,那么 512 字节长的数据会被保存两次吗?
如果是这样,有没有办法只保留对索引的引用而不是对 varchar 本身的引用?
简而言之,我的问题是,在 InnoDB 中是否有一种有效的方法来保存长 VARCHAR 字段的外键?
非常感谢,
亚尼夫
我进行了一个简单的测试:创建 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 版本中是这样。
是的,如果VARCHAR(512)
引用表上有列,则数据将存在两次。
我建议您让引用表的外键引用第一个表的整数主键,而不是 512 字节数据。这就是标准化的全部内容。
保持较小的密钥大小总是好的。您可以VARCHAR
通过在插入时生成一个额外的校验和列来解决索引大的问题。此校验和字段将包含散列算法的输出,CRC32()
或者可能MD5()
包含较大列的输出。