仅使用varchar作为外键的MySQL表

仅使用varchar作为外键的MySQL表,mysql,foreign-keys,innodb,varchar,Mysql,Foreign Keys,Innodb,Varchar,我有一个表,其中有一个唯一的VARCHAR(512)字段。我想让另一个表保存对第一个表的外键引用。两个表都使用InnoDB。 如果我向第二个表添加一个VARCHAR(512)键,并在其上添加一个外键约束,512字节长的数据会被保存两次吗 如果是这样,有没有一种方法只保存对索引的引用而不保存对varchar本身的引用 简而言之,我的问题是,在InnoDB中有没有一种有效的方法来保存长VARCHAR字段的外键 多谢各位 Yaniv是,如果在引用表上有一个VARCHAR(512)列,则数据将存在两次

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

如果是这样,有没有一种方法只保存对索引的引用而不保存对varchar本身的引用

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

多谢各位


Yaniv

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


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

我运行了一个简单的测试:创建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
索引的问题。这个校验和字段将包含散列算法的输出。CRC32()或者可能包含较大列的
MD5()

但是,当varchar的索引存在时,添加一个整数键不是一种浪费吗?我真正想要的是一种只引用索引内容的方法。如果你需要一个行的“句柄”,而你唯一的选择是一个512字符的varchar列,这不是浪费。这种“只引用索引内容的方法”的想法在我看来似乎毫无意义;除了索引中的值,你不能引用任何东西。所有的数据真的有512字节长吗?存储应限于每行记录的大小。如果可能,最好使用整数主键和外键。允许的最大大小为512字节,但大多数条目的长度约为100字节。这就是我使用VARCHAR类型的原因,因为它应该只使用大约100个字节,而不是浪费空间。