MySQL BIGINT(20) 与 Varchar(31) 性能对比

标签 mysql performance benchmarking

我读过像 23423423423423423637 这样的 bigint 对于 primare 唯一键比像 961637593864109_412954765521130 这样的 varchar 要好但是 有多大 当我永远不会排序但只选择时有 100 万行时,差异有多大/更新一行。使用 varchar 对我来说会舒服得多,当性能差异低于 30% 或任何其他值时,我将继续使用它。我找不到任何基准。

最佳答案

这确实需要衡量,我们可以根据我们所知道的和我们假设的进行一些“猜测”,但这些只是猜测。

您没有提及此表是 InnoDB 还是具有动态行的 MyISAM 或具有固定长度行的 MyISAM。这会有所不同。

但对于像您发布的那样的值,'961637593864109_412954765521130'(31 个字符),假设您使用的是单字节字符集(例如 latin1),或者将这些特定字符编码为的字符集单个字节(例如 utf8)...

对于 InnoDB 和 MyISAM 动态格式,该行有 31+1-8=24 个额外字节。 (BIGINT 适合 8 个字节,31 个字符的 VARCHAR(31) 值将使用 32 个字节。)

对于具有固定长度行的 MyISAM 表,这将是每行 23 个字节的差异。 (为所有31个字符预留空间,不必存储长度。)

该主键值也将在每个索引中重复,因此每个索引也会增加空间。

假设使用 BIGINT 的表行为 120 字节,使用 VARCHAR 的行为 144 字节,则增加了 20%。行越大,增加的百分比就越小,反之亦然。

对于 1,000,000 行(我很想说“one meelyun rows”,就像 Dr. Evil 将他的小指放在嘴角说“一百万美元”一样),每行额外的 24 个字节总计大约 24MB。

但这并不是那么容易。就 InnoDB 空间而言,这是行如何“适合” block 的问题。平均行大小越大, block 中的可用空间量就越大。

如果您除了将行存储在磁盘上之外不对这些行执行任何操作,那么它实际上只是增加了磁盘空间,以及用于备份的额外时间和空间。


如果“144 字节”行与“120 字节”行在一个 block 中的容量相同,那么您将看不到任何空间差异。但是,如果一个 block 中适合的行更少,那么 block 就会更多,InnoDB 缓冲池中的空间更多,输入/输出更多,等等。


对于单个行的查询,无论是通过主键值还是通过一些其他唯一索引查找,差异都可以忽略不计。

如果您正在处理更大的结果集,那么这就是用于准备结果集的额外内存,以及要传输到客户端的额外字节等。


如果 VARCHAR 键的设计方式是一起访问的“组”行具有键值的相同前导部分,那么对于 InnoDB,实际上可能会有一些性能改进。这是因为主键是簇键...满足查询所需的行更有可能位于同一个 block 中,而不是分布在一堆 block 中。

反之,如果执行了插入和删除操作,一些 block 中就会有更多的空闲空间。 (通过删除,已删除行的空间保留在 block 中;要重复使用,您需要插入一个具有相同键值的行(或者至少一个键值足够接近以使其位于同一 block 中.) 并且通过随机插入,我们将得到 block split 。

关于MySQL BIGINT(20) 与 Varchar(31) 性能对比,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42566120/

相关文章:

c++ - 将未使用的类数据成员存储在磁盘上

像 nosetests 这样的 Python 基准测试工具?

java - 在 JMH 中对 ArrayList.add() 进行基准测试时出现 OutOfMemoryError

c# - 比较 Math.Log 和 Math.Pow

php - 更新脚本随机停止

mysql - 用另一个 MySQL 表的值更新一个 MySQL 表

java - 在 Android 上解析 ~1 MB JSON 非常慢

performance - Hyperledger Fabric可扩展性

mysql - 错误的 unicode 字符串

mysql - 如果我将全局 event_scheduler 关闭,运行事件会发生什么