Question

I have a table with a single unique VARCHAR(512) field. I want to have another table hold a foreign key reference to this first table. Both tables use InnoDB. If I add a VARCHAR(512) key to the second table and add a foreign key constraint on it will the 512 bytes long data be held twice?

If so, is there a way to hold only a reference to the index and not to the varchar itself?

In short, my question is, in InnoDB is there an efficient way to hold foreign keys to long VARCHAR fields?

Thank you very much,

Yaniv

Was it helpful?

Solution

Yes, if you have a VARCHAR(512) column on the referencing table, the data will exist twice.

I recommend that you make the referencing table's foreign key refer to an integer primary key for the first table, not the 512-byte data. This is kind of what normalization is all about.

OTHER TIPS

I ran a simple test: create 3 tables, one to hold the data itself with two columns, and ID (int) and the data (varchar[120]), another table that uses the ID as foreign key and a last one that uses the data as foreign key:

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;

Inserted 100 records in each table and compared the final table size:

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

So I guess the data is NOT replicated in varchar foreign key, well, at least in MySQL 5.1 version.

Keeping the key size small is always good. You could get around the problem of having a large VARCHAR indexed by instead having an additional checksum column that you generate at insert time. This checksum field would contain the output of a hashing algorithm CRC32() or maybe MD5() of the larger column.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top