本文由云+社区发表
一、从常见的报错说起
故事的开头我们先来看一个常见的sql报错信息:
相信对于这类报错大家一定遇到过很多次了,特别对于OMG这种已内容生产为主要工作核心的BG,在内容线的存储中,数据大一定是个绕不开的话题。这里的数据“大”,远不止存储空间占用多,其中也包括了单个(表)字段存储多、大,数据留存时间长,数据冗余多,冷热数据不明显导致的体量大,访问峰值随着热点变化明显,逻辑处理复杂导致数据存储压力放大等等。回到这个报错的问题上来,我们先来看一下这个表的结构:
看到这里,我相信大家会有不同的处理方式了,这里就不对各种处理方式的优劣做比较了,仅仅叙述使用频率较高的两种处理方式。根据报错的指引,把两个大的varchar(22288)改成text、blob
根据业务特点,缩小varchar的存储长度,或者按照规则拆分成多个小的vachar和char
这两种的处理方式也各有优缺点,把字段改成text或者blob,不仅增大了数据存储的容量,对这个字段的索引页只能采用前缀或者全文索引了,如果业务侧存储的是json格式的数据,5.7支持json数据类型是个不错的选择,可以针对单个子类进行查询和输出。同样如果缩小和拆分的话就比较依赖业务的场景和逻辑需求了,业务使用的逻辑上需要修改,工程量也需要评估。
二、深入探索
接着我们再来深入分析下关于限制大小“65535”的一些容易混淆的概念。
1、“65535”不是单个varchar(N)中N的最大限制,而是整个表非大字段类型的字段的bytes总合。
---------------------------------------------------------------------------------------------
Every table (regardless of storage engine) has a maximum row size of 65,535 bytes. Storage engines may place additional constraints on this limit, reducing the effective maximum row size.
---------------------------------------------------------------------------------------------
2、不同的字符集对字段可存储的max会有影响,例如,UTF8字符需要3个字节存储,对于VARCHAR(255)CHARACTER SET UTF8列,会占用255×3 =765的字节。故该表不能包含超过65,535/765=85这样的列。GBK是双字节的以此类推。
3、可变长度列在评估字段大小时还要考虑存储列实际长度的字节数。例如,VARCHAR(255)CHARACTER S