MySQL 数据库 Schema 设计的性能优化②:合适的数据类型

实际上在很多数据库的设计优化文档中都有关于通过优化数据类型的优化说明内容,在 MySQL 中,我们同样也可以通过数据类型的优化达到优化整个 Schema 设计的目的。

优化数据类型提高性能的主要原理在于以下几个方面:

  1. 通过选用更“小”的数据类型减少存储空间,使查询相同数据需要的 IO 资源降低;
  2. 通过合适的数据类型加速数据的比较;

下面我们还是通过分析一些常用数据类型的数据存储格式和长度来看看哪些数据类型可以在优化中利用上吧。

①数字日期类型

我们先来看看存放长度基本固定的一些数据类型的存储长度和取值范围。

对于数字类型,这里分别列出了整数类型和小数类型,也就是浮点数类型。实际上,还有一类通过二进制格式以字符串来存放的数字类型如 DECIMAL(DEC)[(M[,D])],NUMERIC[(M[,D])],由于其存放长度主要通过其定义时候的的 M 所决定,M 定义为多大,则实际存放就有多长。M 代表整个位数长度,而 D 则表示小数点后的位数,默认 M 为 10,D 为 0。一般来说,主要用在固定精度的场合,由于其存放长度较大,而且考虑到这种数据完全可以变化形式以整数存放,所以笔者个人并不是特别推荐。

对于数字的存储,一般使用到浮点型数据的场合也不应该太多。主要出于两个原因,一个是浮点型数据本身实际上是一个并不精确的数字,只是一个近似值,另一个原因就是完全可以通过乘以一个固定的系数转换为整型数据来存放。这样不仅可以解决数据不精确的问题,同时也让数据的处理更为高效。

时间存储格式总类并不是太多,我们常用的主要就是 DATETIME,DATE 和 TIMESTAMP 这三种了。从存储空间来看TIMESTAMP最少,四个字节,而其他两种数据类型都是八个字节,多了一倍。而 TIMESTAMP 的缺点在于它只能存储从1970 年之后的时间,而另外两种时间类型可以存放最早从1001 年开始的时间。如果有需要存放早于 1970 年之前的时间的需求,我们必须放弃 TIMESTAMP 类型,但是只要我们不需要使用 1970 年之前的时间,最好尽量使用 TIMESTAMP 来减少存储空间的占用。

上面所列出的主要是一些存放固定长度,且我们平时可能常用到的一些类型。通过这个对照表格,我们可以很直观地看出哪种类型占用的存储空间大,哪种占用的空间小。这样,在数据类型选择的时候,我们就可以结合各种类型的存储范围以及业务中可能存在的数据作出对应,然后选择存储空间最先的类型来使用。

②字符存储类型

我们再来看看存放字符的数据类型。

CHAR[(M)]类型属于静态长度类型,存放长度完全以字符数来计算,所以最终的存储长度是基于字符集的,如 latin1 则最大存储长度为 255 字节,但是如果使用 gbk 则最大存储长度为 510 字节。CHAR 类型的存储特点是不管我们实际存放多长数据,在数据库中都会存放 M 个字符,不够的通过空格补上,M 默认 为 1。虽然CHAR会通过空格补齐存放的空间,但是在访问数据的时候,MySQL 会忽略最后的所有空格,所以如果我们的实际数据中如果在最后确实需要空格,则不能使用CHAR 类型来存放。在MySQL5.0.3之前的版本中,如果我们定义 CHAR 的时候 M 值超过 255,MySQL 会自动将 CHAR 类型进行转换为可以存入对应数据量的 TEXT 类型,如 CHAR(1000)会自动转换为 TEXT,CHAR(10000)则会转为 MEDIUMTEXT。而从 MySQL5.0.3 开始,所有超过 255 的定义 MySQL 都会直接拒绝并给出错误信息,不再自动转换。

VARCHAR[(M)]属于动态存储长度类型,仅存占用实际存储数据的长度。其存放的最大长度与 MySQL 版本有关,在 5.0.3 之前的版本 VARCHAR 以字符数控制最存储的最大长度,最大只能存放 255 个字符,占用存储空间的实际大小与字符集有关。但是从 5.0.3 开始,VARCHAR 的最大存储限制已经更改为字节数限制了,扩展到可以存放 65535 bytes 的数据,不同的字符集可能存放的字符数并不一样。也就是说,在 MySQL5.0.3 之前的版本,M 所代表的是字符数,而从 5.0.3 版本开始,M 的代表意思已经是字节数了。VARCHAR 的存储特点是不管我们设定 M 为多大的值,真正占用的存储空间都只有我们所存入的实际数据的大小,和 CHAR 不同的是 VARCHAR会保留我们存入数据最后的空格,也就是说我们存入是什么样,MySQL 返回给我们的也会是什么样。在 VARCHAR 类型字段的数据中,MySQL 会在每个 VARCHAR 数据中使用 1 个或 者 2 个字节用来存放 VARCHAR 数据的实际长度,当我们的实际数据在 255 字节之内的时候,会使用 1 字节来存放实际长度,而大于 255 字节的时候,则需要使用 2 字节来存放。

TINYTEXT,TEXT,MEDIUMTEXT 和 LONGTEXT 这四种类型同属于一种存储方式,都是动态存储长度类型,不同的仅仅是最大长度的限制。四种类型的定义都是通过最大字符数来限制,但是他们的字符数限制实际上是可以理解为字节数限制的,因为当我们使用多字节字符集的时候,实际能存放的字符书并没最大字符数那么多,而是以单字节字符来计算的字符数。此外,由于是动态存储长度类型,所以和 VARCHAR 一样,每个字段数据之前都需要一个存放实际长度的空间。TINYTEXT需要1 个字节来存放,TEXT 需要 2 个字节,MEDIUMTEXT 和 LONGTEXT 则分别需要 3 个和 4 个字节来存放实际数据长度。实际上,除了 MySQL 内 嵌 的 最 大 长 度 限 制 之 外 , 他 们 还 爱 到 客 户 端 与 服 悟 器 端 的 网 络 通 信 缓 冲 区 最 大 值 (max_allowed_packet)的限制。

这四种 TEXT 类型和 CHAR 及 VARCHAR 在实际使用中存在几个不一样的地方:

  • 不能设置默认值;
  • 只有 TEXT 可以使用 TEXT[(M)]这样的方式通过 M 设置大小;
  • 基于这四种类型的索引必须指定前缀长度;

③其他常用类型

除了上面这些字段类型之外会被我们经常使用到之外,我们还会使用到的数据类型主要有以下这些。

对于 BIT 类型,M 表示每个值得 bits 数目,默认为 1,最大为 64 bits。对于 MySQL 来说这是一个新的类型,因为从 MySQL5.0.3 才开始真正实现(在之前实际上是 TINYINT(1)),而且仅仅支持 MyISAM 存储引擎,但是从 MySQL5.0.5 开始 Memory,Innodb 和 NDB Cluster 存储引擎也开始“支持”了。在 MyISAM中,BIT的存储空间很小,是真正的实现了通过bit 来存储,但是在其他的一些存储引擎中就不一样了,因为他们是转换为最小的INT 类型存储的,所以占用的空间也没有节省,还不如直接使用 INT 类的数据类型存放来得直观。

对于 SET 和 ENUM 类型,主要内容基本处于较少变化状态且值比较少的字段。虽然这两个字段所占用的存储空间都较少,但是由于在使用方面较其他的数据类型要略为复杂一些,所以在实际环境中一般使用还是较少。

谁都知道,数据量(这里主要指数据记录条数)的增加肯定会让数据库的检索查询效率降低。所以很多时候人们大都希望通过减少数据库中关键表的记录条数来获得数据库性能的提升。实际上,除了这种通过控制数据记录条数来控制数据总量的办法之外,我们还可以通过选择更小的数据类型来让数据库通过更小的空间存放相同的数据量,这对于检索同样的数据所带来的 IO 消耗自然会降低,性能也就很自然得到了提升。

此外,由于 CPU 对不同数据的处理方式不一样,就会造成不同类型的数据在各种运算处理如比较,排序等方面的处理效率存在差异。所以,对于我们需要经常进行比较计算以及排序等消耗 CPU 资源的字段,应该尽量选择处理更为迅速的字段类型。如通过整数类型代替浮点数或者字符类型。

全部评论

相关推荐

04-24 13:51
已编辑
西安电子科技大学 Java
👋个人背景:211计算机混子,代码能力一般,春招急头白脸参加央国企最后拿下这两个offer👏offer1:中广核工程公司驻陆丰仪控调试,待遇19+4,离家1800km💯offer2:张家口卷烟厂待遇未知,应该有13个(猜测),离家500km牛油们帮忙选一下,家里人不是很喜欢卷烟厂这个offer,但是蜀黍烟草局下岸了
鸿雁于飞:先说offer1:中广核工程公司驻陆丰仪控调试(待遇19+4) 中广核这艘央企大船还是很稳的,集团综合效益稳居央企前列。但你得搞清楚,这个19+4的"19"是总包,不是到手数——招聘宣传待遇里把所有能算的都算进去了,饭卡福利积分啥的全包含,有牛油分享实际到手大概打七折。试用期到手可能就四五千的水平,转正后基本工资4800左右,其余靠绩效、年终、大修费撑着。不过核电的工作环境有点"牢笼感"——核电站位置偏僻,远离繁华都市。工程公司是承包商性质,干活比业主公司累,而且大概率要经常出差,有的岗位年出差天数100天以上。最大问题是你这1800km的距离过于离谱,核电员工工作强度最小的时候一周也就回一次家,离得远回家成本高,夫妻感情和亲子关系都是现实考验。说白了:高薪是拿青春和生活换的。 再来看offer2:张家口卷烟厂(待遇约13个) 张家口卷烟厂是河北中烟下属三家卷烟厂之一,河北中烟主打的"荷花"系列连续多年位居全国高端卷烟品牌销量前列。烟草系统薪资由基本工资+绩效+年终奖构成,综合年薪普遍显著高于当地平均水平,六险二金齐全,福利拉满。有人问"13个是不是太平平无奇了"——关键张家口是四线城市,生活成本低,这13万的购买力相当于深圳的二十多万。离家500km,开车半天到家,周末回趟家完全可行,幸福感直接上两个档次。中广核的牛油说了句大实话: "哪个核电站好?永远是离家近的那个最好。" 选烟厂同理。 但是,卷烟厂的坑你得清楚: 首先卷烟厂和烟草局不一样,卷烟厂是生产操作类岗位,很多要三班倒。报考条件明确写了要能"胜任夜班工作和长时间站立工作"。一线操作工每天盯着流水线卷烟,工作内容高度重复,有入职的人描述为"食之无味弃之可惜"。有牛油直言"卷烟厂和商业性质的烟草公司不一样,前者很坑很累"。其次你家里人不是不喜欢,而是担心你这211计算机科班出身,进了烟厂干操作工,技能会快速退化,未来如果行业改革,技术壁垒不高,转行比较困难。等你干两年再跳出来,技术栈全忘干净了,回头再去敲代码,发现连应届生都卷不过。 老牛油的灵魂三问: 1. 你是更怕穷,还是更怕想家? 如果特别恋家的人跑1800km之外,第一年哭鼻子的概率高达80%。陆丰那地方偏僻单调,核电基地又远又闷,闲下来除了打游戏没啥娱乐,社交圈也窄。找个对象都费劲——牛油亲测核电站"狼多肉少"。 2. 你的代码能力有多"一般"? 如果真的一般,仪控调试和你专业匹配度不算高,这活儿主要是工程改造设计、现场实施管理、在建机组设计审查等,偏工程向而非纯软开。干两年后跳回互联网赛道,竞争力不一定有明显提升。反倒是烟厂不需要你写代码,进去就是稳定躺平。 3. 烟草局下岸这事儿会不会让你耿耿于怀? 如果烟草局是你第一志愿,烟厂只是plan B,那得想清楚:进去了可能每天看着天花板想"如果当初去了烟草局该多好",这种内耗比钱少还折磨人。如果你能接受"反正都是烟草系统,先进去再说"的心态,那倒无所谓。 一句话总结: 如果年轻想拼想闯做技术积累,中广核虽然累和远,但简历上央企核电的金字招牌确实有含金量,加上到手收入在这两个选项里确实更高,考虑到你个人经济情况和家庭状况,假如家里不需要你常回去照顾,家里有兄弟姐妹帮手分担,那先去核电待三四年,积累经验再跳槽也不失为一步棋。 如果想安稳过日子离家近当"人上人",烟厂低线生活成本加持,加上稳定的编制和福利体系,在张家***得滋润,幸福感吊打陆丰。尤其家里人是那种离不开你的,有烟厂的稳定且离家近,比任何高薪都实在。
点赞 评论 收藏
分享
03-10 11:23
门头沟学院 Java
鹿LF:计算机面试就跟数学题一样,没什么实际价值,但只能这么筛选,本质是考察你的努力,智力和学习能力
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务