我目前正在决定是使用整数类型还是仅使用典型的字符串类型(例如字符变化(255),which is the default in Rails),因为我不确定索引的性能差异.
这些列是枚举.它们具有固定的大小,可以获得它们可能具有的值.大多数枚举长度不超过5,这意味着索引在应用程序的整个生命周期中或多或少都是固定的;因此,整数和字符串索引的节点数相同.
但是,要编入索引的字符串可能长约20个字符,在内存中大约是整数的5倍(如果整数是4个字节,并且字符串是每个字符1个字节的纯ASCII,那么这就成立了).我不知道数据库引擎如何对索引进行索引,但是如果它需要“扫描”字符串直到它完全匹配,那么本质上这意味着字符串查找比整数查找慢5倍;直到匹配整数查找的“扫描”将是4个字节而不是20个.这就是我想象的:
查找值为(整数)4:
scanning………………………. FOUND | getting records…
|BYTE_1|BYTE_2|BYTE_3|BYTE_4|BYTE_5|BYTE_6|BYTE_7|BYTE_8|…|
查找值为(string)“some_val”(8字节):
scanning………………………………………………………………………….
FOUND | getting records…
|BYTE_1|BYTE_2|BYTE_3|BYTE_4|BYTE_5|BYTE_6|BYTE_7|BYTE_8|…|
我希望这是有道理的.基本上,因为整数占用较少的空间,所以它可以比其字符串对应物更快地“匹配”.也许这是一个完全错误的猜测,但我不是专家,所以这就是我问你们的原因!我想this answer I just found似乎支持我的假设,但我想确定.
列中可能的值的数量在使用任何一个时都不会改变,因此索引本身不会改变(除非我向枚举添加了新值).在这种情况下,使用整数或varchar(255)会有性能差异,还是使用整数类型更有意义?
我问的原因是Rails的枚举类型将整数映射到字符串键,但它们并不意味着是面向用户的列.实质上,您无法验证枚举值是否有效,因为无效值将导致ArgumentError,然后才能运行任何验证.使用字符串类型将允许验证,但如果有性能成本,我宁愿只是解决验证问题.
string … 20 characters long,which in memory is roughly 5x that of
the integer (if an integer is 4 bytes,and the strings are pure ASCII
at 1 byte per character,then this holds)
确切地说,字符类型(text或varchar)占用磁盘上20个ASCII字符和RAM中23个字节的正好21个字节.详细评估:
> What is the overhead for varchar(n)?
同样重要的是:COLLATION规则可以使排序字符数据更加昂贵 – 与数字数据类型不同:
> Would index lookup be noticeably faster with char vs varchar when all values are 36 chars
在大多数情况下,索引大小可能是性能差异的主要原因.考虑每个索引元组的开销(基本上与表相同):项指针为4个字节,元组头为24个字节.因此,整数的索引元组将达到36个字节(包括4个字节的对齐填充),对于具有20个ASCII字符的varchar(20),它将是52个字节(也包括填充).细节:
> Configuring PostgreSQL for read performance
抛开所有理论:最好只测试:
> Measure the size of a PostgreSQL table row
Postgres 9.5引入了一种用于对长字符串数据进行排序的优化(关键字“缩写键”).但Linux上某些C库函数中的错误迫使该项目禁用Postgres 9.5.2中非C归类的功能. Details in the release notes.
但是,如果您实际使用Postgres枚举类型,则大多数这些注意事项都无关紧要,因为无论如何都会在内部使用整数值实现. The manual:
An
enum
value occupies four bytes on disk.
旁白:varchar(255)曾经对sql Server的早期版本有意义,它可以在内部使用更高效的数据类型,最多可达255个字符.但奇数长度限制255个字符对Postgres的性能没有特别的影响.