问题 应该在mysql中避免使用mediumint吗?


我发现以下博客文章的评论建议不要使用mediumint:

即使在MySQL中,也不要使用[24位INT]。它是愚蠢的,它很慢,实现它的代码是一个爬行的恐怖。

4294967295和MySQL INT(20)语法Blows

stackoverflow的答案还指出SQL Server,Postgres和DB2不支持mediumint。

MySQL中的tinyint,smallint,mediumint,bigint和int有什么区别?

应该避免使用中,还是应该在最能代表我存储数据的情况下继续使用?


8459
2017-08-12 03:44


起源

这是虚假的经济。现代处理器的自然宽度为32或64位,db必须付出额外的努力才能实现24位整数宽度。 - Jim Garrison
@JimGarrison我真的怀疑这是一个很重要的因素。它可以存储为内存中的32位(或不存在,但并不重要),并且记录在24位上。 (在int上节省高达25%的空间..) - user2864740


答案:


InnoDB将MEDIUMINT存储为三个字节的值。 但是当MySQL必须进行任何计算时,三个字节MEDIUMINT被转换为8个字节的unsigned long int(我假设现在没有人在32位上运行MySQL)。

有利有弊,但你明白“这是愚蠢的,它很慢,实现它的代码是一种爬行的恐怖”推理不是技术性的,对吧?

我想说当磁盘上的数据大小至关重要时,MEDIUMINT是有意义的。即当一个表有这么多记录,甚至一个字节的差异(4字节INT与3字节MEDIUMINT)意味着很多。这是一种罕见的情况,但可能。

mach_read_from_3和mach_read_from_4 - InnoDB用于从InnoDB记录中读取数字的原语是类似的。他们都返回ulint。我打赌你不会注意到有什么不同 任何 工作量。

只需看看代码:

ulint
mach_read_from_3(
/*=============*/
        const byte*     b)      /*!< in: pointer to 3 bytes */
{
        ut_ad(b);
        return( ((ulint)(b[0]) << 16)
                | ((ulint)(b[1]) << 8)
                | (ulint)(b[2])
                );
}

你认为它比这慢得多吗?

ulint
mach_read_from_4(
/*=============*/
        const byte*     b)      /*!< in: pointer to four bytes */
{
        ut_ad(b);
        return( ((ulint)(b[0]) << 24)
                | ((ulint)(b[1]) << 16)
                | ((ulint)(b[2]) << 8)
                | (ulint)(b[3])
                );
}

9
2017-08-12 05:14



好,谢谢。我想我想确认MySQL在内部处理mediumint的方式是否有什么特别糟糕的,或者它是否真的是非标准的,应该避免。如果它适合存储的数据,听起来好像可以使用。 - Stoz


在宏伟的计划中,取得成功是一项巨大的成本。简单的函数,表达式以及更少的数据格式在查询所花费的时间内无关紧要。

另一方面,如果您的数据集太大而无法保持缓存,则获取行的I / O开销会更加显着。粗略的经验法则是,非缓存行需要10个  只要缓存一个。因此,缩小数据集(例如使用较小的数据集) *INT可能 为您带来巨大的性能优势。

这个论点适用于 ...INTFLOAT VS DOUBLEDECIMAL(m,n)DATETIME(n)等等(需要进行不同的讨论 [VAR]CHAR/BINARY(...) 和 TEXT/BLOB。)

对于具有汇编语言背景的人...

  • 一张桌子 容易 混合数字和字符串,从而阻止“对齐”值的尝试。
  • MySQL一直处理各种硬件(大/小端,16/32/64位) 具有二进制兼容性。请注意@akuzminsky提供的代码如何避免对齐和字节序问题。如果硬件只有16位,它可以让编译器处理32位问题。
  • 测试特殊情况的代码可能会超过简单编写通用代码。
  • 我们说的通常不到总行处理时间的1%。

因此,编写代码的唯一理智方法是在字节级工作,并忽略寄存器大小并假设所有值都是错误对齐的。

对于优化,按重要性顺序:

  1. 计算磁盘命中数。触摸磁盘绝大多数是查询中最昂贵的部分。
  2. 计算触摸的行数。找到一行(通过BTree等)需要一些CPU。但是,请注意,很少有安装是CPU限制的;那些往往指数不佳的人。 (经验法则:InnoDB数据或索引块通常有100行。)
  3. 只有现在才解析该行。

经验法则:如果暂定优化没有(通过封套后的计算)产生10%的改进,请不要浪费你的时间。相反,寻找一些更大的改进。例如,索引和摘要表通常提供10倍(不仅仅是10%)。


3
2018-04-27 16:10



谢谢,还有MySQL呢 MEDIUMINT (3个字节)整数?它会导致CPU做额外的工作来对齐寄存器上的数据吗?这就是我被告知的 这里 - Accountant م
@Accountantم - 我的背景非常理解“字对齐”。但是,我声称,在这种背景下,它确实无足轻重。我在答案中加了一堆。 - Rick James