MySQL UNIQUE密钥设计:复合INT+VARCHAR密钥与单一col VARCHAR密钥



我正在考虑MySQL 5.6 InnoDB表的以下模式。我很难决定使用哪把钥匙:

"CREATE TABLE IF NOT EXISTS `context` ("
"  `text_id` INT NOT NULL AUTO_INCREMENT,"
"  `doc_id` INT NOT NULL,"
"  `text` VARCHAR(255),"
"  PRIMARY KEY (`text_id`),"
"  UNIQUE KEY `text_uk` (`text`),"                  <<< OPTION 1
"  UNIQUE KEY `docidtext_uk` (`doc_id`, `text`),"   <<< OPTION 2
") ENGINE=InnoDB "

我可以要求列text是唯一的(选项1),也可以在text中允许一些重复条目,而在doc_id+text上放置一个复合唯一键(选项2)。从存储的角度来看,选项1显然更高效,但查询速度是我们最关心的问题

考虑到text很长,因此是一个低效的唯一密钥,我怀疑使用复合密钥可能会导致更快的查询(注意doc_id是一个整数,因此相对非常高效)。然而,我对MySQL内部还不够熟悉,无法理解复合键是否以这种方式工作。

如果阅读速度是我们最关心的问题,那么这些选项中的哪一个是最佳实践?保留两把钥匙有什么害处或好处吗?

注:

  • 查询此表的唯一函数始终可以访问doc_idtext的值(此函数的唯一目的是查找text_id)
  • 该表目前没有数据,但我们预计它最终将容纳大约10亿行
  • 每个doc_iddoc_id列的其他行中最多有99个重复项
  • text列中可能有数百万个单元格的前20多个字符是相同的(所有文本片段都很短,属于同一个一般主题)
  • 目标是对text列执行重复数据消除。对于这个特定的应用程序,这样做有望节省大量空间

将Text_id作为主键
当您开始遇到性能问题时,添加doc_id和text的索引并包含text_id。小心过早优化。

根据我的阅读,您需要将文档连接到文本。出于某种有趣的原因,这段文字可以复制。就我个人而言,我永远不会寻找重复的文本并为此进行优化,但人们很有趣,所以这里是:

  • 创建一个仅包含文本的表对文本进行哈希(这样您可以获得更少的数据),并从中创建唯一索引。您的文本现在可以任意长。

  • 插入到链接文档和文本的表中,通过外键链接它们。

祝贺您,您已经对某些内容进行了微优化。现在,如果你决定真的,真的压缩所有可能的空间,并对其进行超级优化,那么你可能会转向MySQL的存储引擎,与InnoDB相比,你会得到高达的空间减少12倍。

目标是什么?

  • 是否要使用text来节省空间?似乎不太可能存到足够的钱
  • "规格化"text,以便如果需要更改字符串,可以在一个位置进行更改?没有任何暗示
  • 发现哪个doc包含给定的text?显然不需要
  • 在其他几个表中节省空间,否则这些表中会有text?显然只有另外一张桌子

结论:由于你似乎不需要任何东西来证明这个表的合理性,所以

亲吻。

只要把text放在需要它的表中。如果我在4个要点中的一个上错了,我会改变我的答案。

编辑

如果会有很多重复的字符串,并且目标是重复数据消除,我建议

CREATE TABLE context (
text_id INT UNSIGNED NOT NULL AUTO_INCREMENT,
text VARCHAR(255) NOT NULL,
PRIMARY KEY(text_id),
UNIQUE(text)            -- for finding dup
) ENGINE=InnoDB;            -- because of the way it clusters
INSERT INTO context (text) VALUE ('$escaped_text')
ON DUPLICATE KEY UPDATE text_id = LAST_INSERT_ID(text_id);  -- see ref manual
$text_id = LAST_INSERT_ID();

如果字符串往往很长,请改用VARBINARY,并在客户端中压缩/解压缩。对于典型的文本,压缩会将文本缩小3倍。

相关内容

  • 没有找到相关文章

最新更新