【发布时间】:2010-10-03 10:56:46
【问题描述】:
我想知道在 MySQL 中使用 UNSIGNED 标志定义一些整数字段有什么积极影响吗?它是否使查询更快或数据库更小?还是只在担心上限的时候才去管它?
【问题讨论】:
标签: mysql database-design
我想知道在 MySQL 中使用 UNSIGNED 标志定义一些整数字段有什么积极影响吗?它是否使查询更快或数据库更小?还是只在担心上限的时候才去管它?
【问题讨论】:
标签: mysql database-design
根据 MySQL 5.1 手册的section 10.2:
在非严格模式下,当 超出范围的值被分配给 整数列,MySQL 存储值 代表对应的 列数据类型的端点 范围。如果您将 256 存储到 TINYINT 或 TINYINT UNSIGNED 列,MySQL 分别存储 127 或 255 个。什么时候 浮点或定点列 被分配的值超过 指定的隐含范围(或 默认)精度和规模,MySQL 存储代表的值 该范围的相应端点。
因此,只有在您关心上限时才真正需要使用 UNSIGNED。此外,添加 UNSIGNED 不会影响列的大小,只是数字是 represented。
【讨论】:
除非您试图从价值中获得最大收益并且不需要负值,否则这无关紧要。
例如,假设您要存储 0-255。
您可以使用 tinyint,但前提是您将其用作 unsigned。
我见过的很多数据库,人们都懒得这样优化,最后得到一些相当大的表,因为他们一直都在使用 INT。
不过,如果您说的是 int 与 unsigned int,则根本没有性能影响或空间影响。
从标准的角度来看,我总是使用无符号,并且仅在我知道需要负值时才使用有符号。
【讨论】:
在性能或存储方面,完全一样。
作为一般规则,请使用更适合您的值:如果您只需要正值,请将值存储为 UNSIGNED,否则,让它成为默认值 [SIGNED]。
为 PRIMARY AUTOINCREMENT 列设置 SIGNED 值时会出现一个问题:自动生成的数字的计数从 1(不是最小的负数)开始,并且可能的值将更早结束,因为您将只使用值的一半。所以在这种情况下(PRIMARY + AUTOINCREMENT 列)最好存储为 UNSIGNED。
【讨论】:
当列只包含正数时使用无符号。
它不会影响列上的任何 I/O 性能,因为它仍会占用完全相同的空间量。
【讨论】:
它将提高性能,假设您要搜索数量
没有“未签名”: 流程,由于数量字段是一个“int”并且你有这个字段的索引,所以MySQL会定义范围为-2147483648到500,它会根据这个范围得到结果。
使用“未签名”: 流程,由于数量字段是一个“int”和“unsigned”,并且你有这个字段的索引,所以MySQL会将范围定义为0到500,它会根据这个范围得到结果。
【讨论】:
在这里,您可以看到 MySQL documentation 的 SIGNED 与 UNSIGNED INT 的范围。您很快就会注意到 UNSIGNED INT 的下限始终为 0,因此它永远不会是负数。
Type Storage Minimum Value Maximum Value
(Bytes) (Signed/Unsigned) (Signed/Unsigned)
TINYINT 1 -128 127
0 255
SMALLINT 2 -32768 32767
0 65535
MEDIUMINT 3 -8388608 8388607
0 16777215
INT 4 -2147483648 2147483647
0 4294967295
BIGINT 8 -9223372036854775808 9223372036854775807
0 18446744073709551615
【讨论】:
警告,Unsigned Int (UINT) 和实体框架或 ADO.NET 存在问题。它可能涉及 MySql 连接器版本 6 的集成问题。
根据我的经验,UInt 被 EF 读取为Long,这可能会引发一些精度问题,因为UInt 不是Long。任何不熟悉该问题的人都可能会感到头疼。
其他问题:
【讨论】:
我更喜欢使用 UNSIGNED SMALLINT(或 MEDIUMINT)而不是 SIGNED INT。 它节省了 2 个(或 1 个)bytes,这有时会在大型数据集上提供更好的性能,尤其是索引列。
【讨论】: