PG_字符串探究
前言
varchar和char是两种最主要的字符串类型,不同数据库在实现方式以及两者的性能上存在很大差异,以下就mysql和PG进行对比。以下MYSQL以InnoDB引擎为例
VARCHAR
varchar类型用于存储可变长字符串,是最常见的字符串数据类型。它比定长类型更节省空间,因为它仅使用必要的空间,通常一个varchar类型的字符串,占用的实际存储空间为“实际长度+额外记录字符串信息的字节”,varchar节省了存储空间,所以对性能也有帮助。但是,在对字段进行update操作时;PG和mysql存在较大差异
mysql:
由于行是变长的,在update时可能使行变得比原来更长,这将导致需要额外的工作。如果一个行占用的空间增长,并且在页中没有更多的空间可以存储,在这种情况下,InnoDB引擎会分裂页使行可以放进页内,产生碎片。因此mysql中varchar适合以下场景:
- 字符串列的最大长度比平均长度大很多
- 列很少更新
- 使用了像UTF-8这样复杂的字符集,每个字符都使用不同的字节数进行存储
PG:
实际长度:"4字节+实际长度",PG中采用多版本控制(MVCC)实现事务并发,具体update过程是,先将原记录行进行标记,然后insert一条新记录;不存在MYSQL中的问题。
CHAR
char类型是定长的,数据库总是会根据字符串定义长度分配足够的空间
mysql:
当存储char值时,mysql会删除所有的末尾空格('ABC '会变成'ABC'),char值会采用空格进行填充以方便比较。char适合存储很短的字符串,或所有值都接近同一个长度。例如,char非常适合存储密码MD5值,因为这是一个定长的值。对于经常变更的数据,char也比varchar更好,因为定长的char类型不易产生碎片;对于非常短的列,char也比varchar在存储空间上更有效率,例如用char(1)来存储Y和N的值,如果采用单字节字符集只需要一个字节,而varchar(1)却需要两个,varchar需要1或2个额外字节记录字符串长度,分界点在字符串长度是否大于255字节。
PG:
实际长度:"4字节+实际长度+空白填充",char和varchar性能上没有差别,相反char需要额外的存储空间来填充空白,以及在存储到一个有长度约束的列时需要少量额外的CPU周期检查长度,因此char性能反而更差。
实际项目中如何选择?
以上已经介绍了两种字符类型的区别,在PG中优先考虑varchar类型,MYSQL中根据需求进行选择;那么varchar(5)和varchar(200)存储“hello”的空间开销是一样的,那为什么应该选择更短的列呢?
事实证明更短的列优势更大,更长的列需要消耗更多的内存,因为数据库通常会分配固定大小的内存块来保存内存值。尤其是使用内存临时表进行排序或操作时会特别糟糕。在利用磁盘临时表进行排序时也同样糟糕。
所以最好的策略是只分配真正需要的空间。