在 Firebird 中使用 VarChar 或 Char 而不是 Integer 时的性能、space 和其他观察结果
Performance, space and other observations when using VarChar or Char instead of Integer in Firebird
我经常使用 Integer
类型的列来指定记录的某些 "type",因此 0=TypeA、1=TypeB 等等。我可以将翻译放入列描述中,但值本身并不是人类可读的。该列也可以被索引。
另一种情况是,有时记录有一些简短的唯一字母数字字符串作为标识符。此外,我添加了一个 Integer
ID 作为主键(并且对于该名称只有一个唯一索引),因为我被告知出于性能原因,主键永远不应该是字符串。从名称中获取 ID 后,我会尽可能使用它。
所以问题是,什么性能,space 和其他观察你能告诉我关于在我可以使用整数的地方直接使用字符串吗?这些字符串可以很短,比如 8 个字符甚至更少,7 位 ASCII 就足够了。
此问题主要针对 Firebird 3.0,但我也对一般规则或 Firebird 与其他数据库(如 MSSQL)的比较非常感兴趣。
这个问题不是关于使用自然主键而不是代理主键。
没有固定的规则,它永远是一个权衡。不要一概而论,要考虑用例、易用性和潜在的开销
通常首选整数值,因为它们会导致较小的索引。 Firebird 中的数字索引(64 位整数除外)使用 64 位双精度,这意味着(忽略前缀和后缀压缩等优化),索引中的数字条目将为 8 个字节。
对于字符,它将是最大声明长度(字符数 x 字符集中每个字符的最大字节数),因此 CHAR(8) CHARACTER SET UTF8
将占用 8x4=32 字节,而 CHAR(8) CHARACTER SET WIN1252
占用8x1 = 索引中的 8 个字节(再次忽略一些优化)。
换句话说,如果你使用的那些字符串是 8 个或更少的字符,使用单字节字符集(在这种情况下,即使是像 ASCII 这样的 7 位字符集仍然会使用完整的字节!),那么会有使用整数或字符串值之间没有显着差异。
此外,如果主键将被另一个 table 的外键作为目标,并且您使用了代理项,您现在需要添加一个连接才能查找该代码,而如果您直接将它用作主键,它将立即可用。必须进行额外联接的性能影响可能超过使用代理项的任何预期性能 'benefits'。
与软件开发中的一切一样,这是一种权衡。如果字符串代码仍然很小,如 8 个或更多字符,并且您知道字符串代码不需要更改(级联更新等),那么无论如何:选择字符串代码。
另一方面,如果字符串代码需要定期更改(这会导致级联更新),请使用代理项。如果字符串代码大于 16 字节,请考虑同时实施并执行实际(!)性能测试。如果字符串代码很长(比如 50 个字节或更多),则倾向于使用代理项。
我经常使用 Integer
类型的列来指定记录的某些 "type",因此 0=TypeA、1=TypeB 等等。我可以将翻译放入列描述中,但值本身并不是人类可读的。该列也可以被索引。
另一种情况是,有时记录有一些简短的唯一字母数字字符串作为标识符。此外,我添加了一个 Integer
ID 作为主键(并且对于该名称只有一个唯一索引),因为我被告知出于性能原因,主键永远不应该是字符串。从名称中获取 ID 后,我会尽可能使用它。
所以问题是,什么性能,space 和其他观察你能告诉我关于在我可以使用整数的地方直接使用字符串吗?这些字符串可以很短,比如 8 个字符甚至更少,7 位 ASCII 就足够了。
此问题主要针对 Firebird 3.0,但我也对一般规则或 Firebird 与其他数据库(如 MSSQL)的比较非常感兴趣。
这个问题不是关于使用自然主键而不是代理主键。
没有固定的规则,它永远是一个权衡。不要一概而论,要考虑用例、易用性和潜在的开销
通常首选整数值,因为它们会导致较小的索引。 Firebird 中的数字索引(64 位整数除外)使用 64 位双精度,这意味着(忽略前缀和后缀压缩等优化),索引中的数字条目将为 8 个字节。
对于字符,它将是最大声明长度(字符数 x 字符集中每个字符的最大字节数),因此 CHAR(8) CHARACTER SET UTF8
将占用 8x4=32 字节,而 CHAR(8) CHARACTER SET WIN1252
占用8x1 = 索引中的 8 个字节(再次忽略一些优化)。
换句话说,如果你使用的那些字符串是 8 个或更少的字符,使用单字节字符集(在这种情况下,即使是像 ASCII 这样的 7 位字符集仍然会使用完整的字节!),那么会有使用整数或字符串值之间没有显着差异。
此外,如果主键将被另一个 table 的外键作为目标,并且您使用了代理项,您现在需要添加一个连接才能查找该代码,而如果您直接将它用作主键,它将立即可用。必须进行额外联接的性能影响可能超过使用代理项的任何预期性能 'benefits'。
与软件开发中的一切一样,这是一种权衡。如果字符串代码仍然很小,如 8 个或更多字符,并且您知道字符串代码不需要更改(级联更新等),那么无论如何:选择字符串代码。
另一方面,如果字符串代码需要定期更改(这会导致级联更新),请使用代理项。如果字符串代码大于 16 字节,请考虑同时实施并执行实际(!)性能测试。如果字符串代码很长(比如 50 个字节或更多),则倾向于使用代理项。