此页面为机器翻译。请阅读英文原文。 English

IBSurgeon 文库

VARCHAR 和 INTEGER 字段在键中的区别

我在表中使用整数ID作为主键。如果改用varchar字段会怎样?在这种情况下,特别是对于大表,我会损失性能吗?连接操作还能像整数列那样快吗?

使用varchar或integer,性能应该大致相同。Firebird总是按字节比较索引键,并且只存储值中有效部分。

单字段键首先被转换为三种规范类型之一:带排序规则的字符串、双精度浮点数,以及(遗憾的是)64位整数。日期会转换为双精度浮点数。

具有非字节值排序规则的字符串会被转换为其排序规则格式。这有点像一门玄学,会扩大字符串的大小,但结果是该字符串在与相同排序规则的其他字符串排序时能找到正确的位置。‘A’、‘a’、‘â’、‘á’、‘Ă’、‘ã’、‘ä’、‘å’、‘ă’、‘ą’、‘Ā’都会出现在它们各自指定的位置。(抱歉对你的邮件客户端造成了影响……在我这边,这是’A’的十一个变体。)尾随空格不包含在键中。

双精度浮点数会被处理,使其也能按字节排序–大致是反转符号位,然后是指数,再是尾数,并截断尾随的零。

根据计算机上64位整数的字节序,它们也会被处理,以便按字节比较。这看起来像是一种反向优化,但索引键并不存储在自然边界上,并且它们经过前缀压缩,因此无法使用比逐字节更大的比较方式。

复合键也大致相同。每个部分都被转换为其索引键类型,并填充为4字节的倍数。每四个字节后,Firebird会添加一个字节,表示键中当前字段的位置。因此,在LastName、FirstName、ZodiacSign上的索引会变成1Harr1ison2Ann 3Gemi3ni。这避免了将"Damnation"与"Dam nation"混淆的尴尬。

为什么我上面说"(遗憾的是)"?因为拥有单一的数字格式可以让Firebird在不重建索引的情况下更改数字的大小。但当Borland重新加入64位整数时–InterBase在Vax机上从一开始就有64位整数–某个聪明人意识到双精度浮点数有56位精度,而64位整数有64位。另一方面,Firebird索引设计为能处理一些不精确性……或者剩余的8位可以附加在末尾……随便吧。所以当从Numeric/Decimal 9升级到Numeric/Decimal 12时,你必须重建索引。真遗憾。

“前缀压缩?“当存储页面上第一个键之后的键,或页面上跳转后的第一个键时,Firebird会查看前一个键,截断下一个键开头与前一个键重复的部分,并在开头附加被截断部分的长度。因此,字符串"AAAA”、“AAAB”、“AAAC”、“AABC"变成

“AAAA”、“3B”、“3C"和"2BC”。某些GUID格式存在问题,它们将数字的可变部分放在前面,后面跟着固定部分。这会破坏前缀压缩并增大索引的大小。

“跳转?”–前缀压缩大大减小了索引的大小,减少了I/O,但需要读取整个页面来解读键。对于1K页面来说没问题,但对于更大的页面大小,这种计算变得不可接受。因此,每个索引页面现在都有自己的索引,指向未压缩条目的偏移量。这个索引被称为跳转向量。

Ann Harrision