在MySQL中使用数字行ID的优点是什么?

时间:2014-02-18 22:04:45

标签: mysql sql performance

我是SQL新手,对我而言,关系而不是分层次地思考我的数据集对我来说是一个很大的转变。我希望能够对性能(包括存储空间和处理速度)以及使用数字行ID作为主键而不是更有意义的字符串值的设计复杂性有所了解。

具体来说,这是我的情况。我有一个表(“父”)有几百行,其中一列是字符串标识符(10-20个字符),这似乎是表的主键的自然选择。我有一个第二个表(“child”),其中包含数十万(或可能数百或更多)行,其中每一行引用父表中的一行(因此我可以在子表上创建外键约束)。 (实际上,我有两个类型的表,其中包含一组复杂的引用,但我认为这可以解决这个问题。)

所以我需要子表中的一个列,它为父表中的行提供标识符。天真地,似乎创建列像VARCHAR(20)这样的东西来引用第一个表中的“自然”标识符会导致在存储空间和查询时间方面的巨大性能损失,因此我应该包括父表中的数字(可能是auto_increment)id列,并将其用作子项中的引用。但是,由于我加载到MySQL中的数据还没有这样的数字ID,这意味着增加了我的代码的复杂性和更多的错误机会。更糟糕的是,由于我正在进行探索性数据分析,我可能想要查看父表中的值而不对子表执行任何操作,因此我必须小心不要意外地破坏关系删除行并丢失我的数字ID(我可能通过将id存储在第三个表或类似的东西来解决这个问题。)

所以我的问题是,是否存在我可能没有意识到的优化,这意味着一个包含数十万或数百万行的列,一遍又一遍地重复几百个字符串值比它首次出现的浪费少?我不介意效率的适度折衷,有利于简单,因为这是用于数据分析而不是生产,但我担心我会把自己编码到一个角落,我想要做的每件事都花费了大量的时间跑。

提前致谢。

4 个答案:

答案 0 :(得分:8)

我不会主要关注太空考虑因素。整数键通常占用四个字节。 varchar将占用1到21个字节,具体取决于字符串的长度。因此,如果大多数只是几个字符,varchar(20)键将占用比整数键更多的空间。但不是非常多。

顺便说一句,两者都可以利用索引。因此,访问速度并没有特别的不同(当然,较长/可变长度的密钥对索引性能会产生边际影响)。

使用自动递增的主键有更好的理由。

  1. 您知道最近插入了哪些值。
  2. 如果出现重复项(当然主键不应该出现),很容易确定要删除的内容。
  3. 如果您决定更改其中一个条目的“名称”,则不必更新引用它的所有表格。
  4. 您不必担心前导空格,尾随空格和其他字符奇怪。
  5. 您确实需要为记录中的四个字节支付额外的功能,这些记录专用于可能看起来不太有用的内容。然而,这样的效率还为时过早,可能不值得努力。

答案 1 :(得分:2)

戈登是对的(这并不奇怪)。

在我看来,您不必担心以下注意事项。

当你处理几十个或更少的megarows时,存储空间基本上是免费的。不要担心INT和VARCHAR(20)之间的区别,也不要担心添加额外一列或两列的磁盘空间成本。只要你能以100美元左右购买体面的TB级驱动器就没关系。

INTs和VARCHARS都可以非常有效地编入索引。你不会看到时间表现上的太大差异。

这是你应该担心的。

索引性能存在一个重大缺陷,您可能会遇到字符索引。您希望将创建索引的列声明为NOT NULL,并且您永远不希望执行查询

 WHERE colm IS NULL   /* slow! */

 WHERE colm IS NOT NULL  /* slow! */

这种事情打败了索引。与此类似,如果将函数应用于搜索中的列,则性能将大大降低。例如,不要这样做,因为它也会使索引失败。

 WHERE SUBSTR(colm,1,3) = 'abc'  /* slow! */

要问自己还有一个问题。您是否唯一地标识子表中的行,如果是,如何?他们有某种天然复合主键吗?例如,您可以将这些列放在“子”表中。

 parent       varchar(20)   pk  fk to parent table
 birthorder   int           pk
 name         varchar(20)

然后,您可以拥有像...这样的行。

  parent      birthorder     name
  homer       1              bart
  homer       2              lisa
  homer       3              maggie

但是,如果你试图像这样插入第四行

  homer       1              badbart

你得到一个主键冲突,因为(本垒打,1)被占用。研究如何管理子表的主键可能是个好主意。

包含数字的字符串排序很有趣。例如,'2'在'101'之后。你需要注意这一点。

答案 2 :(得分:0)

您从数值中获得的主要好处是它们更容易“索引”。索引是MySQL用来更容易找到值的过程。

通常,如果要在组中查找值,则必须遍历该组以查找您的值。这是缓慢的并且具有O(n)的最坏情况。相反,如果你的数据是一个漂亮的,可搜索的格式 - 比如binary search tree,如果可以在O(lon n)中找到,那就快得多。

索引是MySQL用来准备要搜索的数据的过程,它会生成搜索树和其他能够快速查找数据的聪明功能。它使得许多搜索速度更快。但是,要执行此操作,必须将要搜索的值与各种“键”值进行比较,以确定您的值是否大于或小于键。

可以对非数字值进行此比较。但是,比较非数字值要慢得多。如果您希望能够快速查找数据,最好的选择是使用整数“密钥”。

答案 3 :(得分:0)

与基于字符串的id相比,数字行id具有许多优点。 在其他答案中提到了大多数。 其中一个是索引。默认情况下,主键在关系数据库中编制索引。因此,拥有数字键总是更有效率。 2.数字字段的存储效率更高 2.数字键的连接速度要快得多。 3.行id可以是外键。数字id是紧凑的存储,使它们高效 我认为在主键上使用自动增量也有其优点

-Thanks _san