【问题标题】:Is using an integral type for an primary key more efficient storage-wise?对主键使用整数类型在存储方面是否更有效?
【发布时间】:2016-05-20 00:43:10
【问题描述】:

这就是我的意思。假设我有一个名为 Names 的表,它只是一个唯一的名称列表,

      Names 
================
      name
================
    "Charlie" 
----------------
    "George"
----------------
    "Bernie"
----------------

以及引用这些名称的另一个表,

        OtherTable  
=========================
  ... |   name    | ....
=========================
  ... | "Charlie" | ....
-------------------------
  ... | "Charlie" | ....
-------------------------
  ... | "Charlie" | ....
-------------------------

数据库引擎是否将实际名称存储在OtherTable 中?还是通过存储一些对它们的隐藏引用来优化?

如果没有,那意味着我应该在Names 中添加一列

id |   Names 
==================
1  |     name
==================
2  |   "Charlie" 
------------------
3  |   "George"
------------------
4  |   "Bernie"
------------------

并像引用它一样

        OtherTable  
=========================
  ... |  name_id | ....
=========================
  ... |    1     | ....
-------------------------
  ... |    1     | ....
-------------------------
  ... |    1     | ....
-------------------------

但是,Names 表上的附加列作为主键是不必要的,因为 names 是唯一的,可以像主键一样服务器(除了查找效率可能稍低) name 因为字符串比较比整数比较慢)。

这不是 Catch-22 的情况吗?

【问题讨论】:

  • 我认为你犯了过早的纳米优化。关系数据库的开发人员在创建索引方面很聪明。您应该使您的架构反映您要解决的问题。这些问题不会对您的应用程序的性能产生影响。问题更可能在于索引缺失或不合适、SQL 编写不当、网络延迟过长等。

标签: sql sql-server tsql database-design


【解决方案1】:

功能和逻辑方面应优先于(非常)次要的效率方面。

链接有意义的列(如name 列)的一个问题是有意义的列往往会发生变化。例如。您可能会发现名称中有错字并想更改它。另一方面,作为 PK 的标识列在这个意义上是没有意义的,因为它除了作为内部使用的标识符之外没有其他意义,并且通常不会显示给用户。由于没有人关心它的真正价值,所以没有人愿意改变它。

字符串可以区分大小写,可以有不同的长度、不同的排序规则、不同的编码和不同的类型(varchar、nvarchar、char、nchar)。 int 很简单(intintint)。


如果您将名称表用作与其他表无关的简单查找表,即,如果您只想将其用作填充文本框的便捷方式但不需要任何参照完整性(没有 Foreign键),那么您可以将其用作主键。


顺便说一句:数据库不会创建任何神奇的、隐藏的引用,而是完全按照您的指示去做。

【讨论】:

    【解决方案2】:

    数据库会将实际数据值存储在表中。如果查找表的主键是字符串,则该字符串可能会在OtherTable 中存储多次。

    根据数据的性质,对Names 表使用合成整数主键可能会更节省空间。但是您可能会为此付出代价,因为您需要在加入两个表时做额外的工作,而不仅仅是从OtherTable 获得name。另一方面,当“Charlie”决定他现在想被称为“Charles”时,合成密钥使更新name 值变得更加容易。与几乎任何架构决策一样,您必须确定权衡是否值得。

    【讨论】:

      【解决方案3】:

      引擎将在“其他”表中存储您在创建列时告诉它的内容(这将是一个字符串)。所以是的,那里有冗余。

      在这个特定的场景中,您通过将字符串替换为对相同数据的较短引用来进行一种数据压缩。许多通用压缩算法做类似的事情。

      如果您关心节省空间,这是一个有效的做法。这是一个复杂的权衡取舍,有很多优点和缺点。

      我认为你没有遗漏任何主要方面。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-04-24
        • 2012-04-24
        • 1970-01-01
        • 2016-02-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-01-19
        相关资源
        最近更新 更多