字符串作为主键的性能损失?

Posted

技术标签:

【中文标题】字符串作为主键的性能损失?【英文标题】:performance penalty of strings as primary keys? 【发布时间】:2010-02-12 08:49:55 【问题描述】:

使用字符串作为主键而不是 bigint 等会有什么性能损失?字符串比较比整数比较昂贵得多,但另一方面,我可以想象 DBMS 在内部将计算散列键以减少惩罚。

我工作的一个应用程序使用字符串作为多个表(mysql)中的主键。改变这一点并非易事,我想知道在性能方面可以获得什么来证明这项工作的合理性。

【问题讨论】:

重复? ***.com/questions/517579/… 【参考方案1】:

另一方面,我可以想象 DBMS 将在内部计算哈希 减少惩罚的关键。

数据库需要维护一个 B-Tree(或类似的结构),其中包含键,以便对它们进行排序。

如果密钥经过哈希处理并将其存储在 B-Tree 中,可以快速检查密钥的唯一性——仍然可以有效地查找密钥。但是您将无法有效地搜索 range 数据(例如使用 LIKE),因为 B-Tree 不再根据字符串值排序。

所以我认为大多数数据库确实将字符串存储在 B-Tree 中,这可能 (1) 占用比数值更多的 空间 并且 (2) 要求 B-Tree 是 如果以任意顺序插入键,则重新平衡(没有像数字 pk 那样增加值的概念)。

实践中的惩罚可以从微不足道到巨大。这完全取决于使用情况、行数、字符串键的平均大小、连接表的查询等。

【讨论】:

【参考方案2】:

在我们的产品中,我们使用 varchar(32) 作为主键 (GUID),我们还没有遇到过这样的性能问题。我们的产品是一个极度过载的网站,对于稳定至关重要。 我们使用 SQL Server 2005。

编辑:在我们最大的表中,我们有超过 3 000 000 条记录,其中包含大量插入和选择。我认为总的来说,迁移到 int key 的好处会非常低,但是迁移时的问题非常高。

【讨论】:

SQL Server 中有一个 GUID 类型。此外,它非常适合复制。【参考方案3】:

需要注意的一件事是页面拆分(我知道这可能发生在 SQL Server 中 - 在 MySQL 中可能相同)。

主键是物理排序的。通过使用自动增量整数,您可以保证每次插入时都会向上插入下一个数字,因此数据库不需要重新排序键。但是,如果您使用字符串,您插入的 pk 可能需要放在其他键的中间以保持 pk 顺序。在插入件上重新排序 pk 的过程可能会很昂贵。

【讨论】:

【参考方案4】:

这取决于几个因素:RDBMS、涉及这些列的索引数量,但通常使用 int 会更有效,其次是 bigint。

任何性能提升都取决于使用情况,因此如果没有表架构和查询工作负载的具体示例,很难说。

除非它在域中有意义(我在想唯一的东西,比如社会安全号码),否则代理整数键是一个不错的选择;当被引用对象发生变化时,引用对象不需要更新其 FK 引用。

【讨论】:

以上是关于字符串作为主键的性能损失?的主要内容,如果未能解决你的问题,请参考以下文章

如何用java中取到作为数据库主键的值?

NHibernate 和字符串主键

Oracle:比较两个不同表中没有主键的字符串列以查找匹配/不匹配的字符串

仅在主表上作为复合主键

int 和guid做主键的时候性能的区别

级联保存具有外键的实体对象作为复合主键的一部分