SQL Server:存在varchar列时char列是否有用?固定长度列优势是否保留?
在SQL Server中混合固定/变长列的性能收益分析
好问题!咱们来拆解一下SQL Server里这个场景的细节,帮你搞清楚混合固定长度列和变长列到底值不值得:
一、固定长度列的收益依然存在,不会被完全抵消
哪怕表中有varchar这类变长列,把其他适合的字段设为固定长度类型(比如char、int、datetime),还是能拿到实实在在的性能好处:
- 更快的列偏移计算:固定长度列的存储位置是完全可预测的,SQL Server不需要额外读取长度标识就能直接定位到列的内容。比如查询一个
int列时,引擎可以直接根据表定义算出它在行中的偏移量,不用像处理varchar那样先读长度值再找内容。 - 更高效的索引存储:如果固定长度列被用作索引键,索引的结构会更紧凑,每页能容纳更多索引条目,减少IO开销,查找速度也更快。
- 更低的行更新碎片风险:固定长度列的更新不会改变行的总长度,只有变长列的更新才可能导致行溢出或页分裂。所以混合场景下,行碎片的产生概率会比全变长列的表低很多。
二、整行变长的影响有限,不会抹杀固定列的优势
SQL Server对混合长度行的存储是做了优化的:
- 行数据会被拆分为固定长度区域和可变长度区域,同时用一个偏移数组记录可变列的位置。固定长度列全部放在前面的固定区域,读取这些列时完全不需要涉及可变区域的解析,效率和全固定长度行几乎一致。
- 只有当你查询或更新变长列时,才会用到偏移数组。如果你的业务查询大多只涉及固定长度列,那性能收益会非常明显。
三、使用固定长度列的注意事项
当然也不能盲目用char代替varchar,否则可能得不偿失:
- 只给真正固定长度的字段用
char:比如性别(char(1))、固定格式的编码(比如char(6)的员工编号),如果字段长度不固定,用char会浪费存储空间(比如char(100)存5个字符的内容,会补95个空格),反而导致每页存储的行数减少,IO成本上升。 - 优先用数值/日期类型:比如
int、datetime2这类原生固定长度类型,比char更节省空间,性能也更好,不要为了“固定长度”把数值转成char存储。
总结
总的来说,只要合理选择固定长度列的应用场景,即使表中有varchar这类变长列,固定长度列带来的性能收益依然存在,不会因为整行变长就完全抵消。
内容的提问来源于stack exchange,提问作者ispiro
相关产品推荐
相关产品推荐

