【问题标题】:MySQL table with only a varchar as a foreign keyMySQL 表只有一个 varchar 作为外键
【发布时间】:2010-11-20 02:27:15
【问题描述】:

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

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

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

非常感谢,

亚尼夫

【问题讨论】:

    标签: mysql foreign-keys innodb varchar


    【解决方案1】:

    我运行了一个简单的测试:创建 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 版本中。

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

      • 但是当 varchar 的索引仍然存在时添加一个整数键不是一种浪费吗?我真正想要的是一种仅引用索引内容的方法。
      • 如果您需要行的“句柄”并且您唯一的其他选择是 512 个字符的 varchar 列,这不是浪费。这种“仅引用索引内容的方式”的想法对我来说似乎是无稽之谈。除了索引索引的值之外,您不能引用任何内容。
      • 所有数据真的都是 512 字节长吗?存储应限制为每行记录的大小。如果可能的话,最好使用整数主键和外键。
      • 允许的最大大小为 512 字节,但大多数条目的长度约为 100 字节。这就是我使用 VARCHAR 类型的原因,因为它应该只使用大约 100 个字节而不浪费空间。
      【解决方案3】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-03-31
        • 1970-01-01
        • 2014-04-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-05-28
        • 2016-11-13
        相关资源
        最近更新 更多