

从网友对 MySQL 手册的一个疑问聊起
source link: https://mp.weixin.qq.com/s?__biz=MzAxNzY0NDE3NA%3D%3D&%3Bmid=2247486017&%3Bidx=1&%3Bsn=3eb5fa2f3d4e1ba0dd8abf22db108959
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

阅读本文大概需要 4 分钟。
在 Go 语言中文网微信群 有人提出了这样的疑问,如下图(文档地址: https://dev.mysql.com/doc/internals/en/date-and-time-data-type-representation.html )
不理解为什么 DATE 是通过 YYYY×16×32 + MM×32 + DD 表示,主要不理解为什么 16、32。我做了讲解,但似乎他还是不太理解。干脆我写篇文章详细讲解下,希望对不清楚的人能有所帮助,答案不是重点, 关键在于分析的过程 。
01
讲一个真实的事情。几年前,某大厂的一个 iOS 开发,说之前接触过 PHP,了解一些后端,于是简单聊了聊(半面试形式)。聊到的一些点,让我感觉他的基础很薄弱,于是我试探性的问:int 类型一般占多大空间?(这样的问题我一般不会问,以免让人感觉“鄙视”他)
他回答:32。我就知道他对这块稀里糊涂的。于是追问一句:单位是什么?他不确定的答道:是字节吧?!
回到 MySQL 中的问题,DATE 用 3 字节的整数类型存储,怎么存?如果不考虑空间,DATE 类型最简单的存储方式可能是,直接将 YYYYMMDD 当做整数存储,比如:20210128。这个数是否可以用 3 个字节存储呢?
1 个字节(byte)是 8 位(bit),3 个字节有 24 位,如果表示无符号整数,最大能表示 (2 << 24) - 1(移位操作优先级低于减法),即 16777215。很显然它比 20210128 小,因此我们不能直接使用 YYYYMMDD 当做整数存储。
如果直接把 YYYYMMDD 形式当做整数,中间会有很多“空洞”,也就是很多数字没有用到,是不连续的,空间利用率太低。比如下图,20210101 比它头一天 20201231 大 8870。
因此,我们可以采用“ 压缩 ”的方式,让日期集合更“紧凑”。MySQL 这里采用的方法就是。具体为什么是 YYYY×16×32 + MM×32 + DD 呢?
02
日期 DD 的范围是:1~31,用 5 个位就可以表示。月份的范围是:1~12,用 4 个位就可以表示,但前面 5 个位被 DD 占用了,因此 MM 得从第 6 位开始,所以需要左移(<<) 5 位,即乘以 32,所以 MM×32 是这么来的 。这样一来,MM 和 DD 一共占据了 5 + 4 = 9 位,3 个字节(24 位)还剩 15 位,也就是说有 15 位可以存放年(YYYY),15 位能表示到 32767 年,远超 2021 年。因此, 对于 YYYY 来说,需要左移 5 + 4 位,也就是 YYYY×32×16。
至于 TIME,因为用秒表示的值可以存入 3 个字节,因此直接将 TIME 转为秒。即 DD×24×3600 + HH×3600 + MM×60 + SS
而 DATETIME 使用了 8 个字节存储,4 个字节存日期,4 个字节存时间。因为空间比较充足,这里的“压缩”没有采用而二进制位,而是直接用十进制的方式。YYYY×10000 + MM×100 + DD, 年月日不会重叠 ,而且没有超过 4 字节能表示的范围,时间一样的道理。
03
如果你问我:为什么 24 位无符号整数最大值是(2<<24) - 1 = 16777215,我建议你可以好好看看 《深入理解计算机系统》。
MySQL 这里使用的技巧值得学习。
最后留一个问题:开头文档中第一点,YEAR 这个类型,使用一个字节存储,你觉得该怎么做?!
Recommend
-
32
-
57
在开发过程中,会经常做的一件事就是在主线程中去刷新 UI,基于这个操作我们作如下几个思考。 为什么 UI 操作一定要在主线程? 如果把 UI 操作放到后台线程会出现什么样的情况呢? 从 UIKit 说起
-
12
从滴滴种树聊起,构建成功游戏化的五大要素 吴依旧 2020-12-18 0 评论...
-
13
最近发现有不少需求可以通过 Nginx JavaScript (NJS)来完成,相比较运行一套完整的 Web 服务来说,轻量高效的方案总是惹人喜爱,更何况这套方案是由 Nginx 官方团队推出,并搭上了繁荣的 JavaScript 生态。 本篇文章先从 NJS 容...
-
8
從「鄙視 jQuery」聊起 -技術鄙視從何而來? 2021-05-10 09:56 PM 17 3,981 前幾天在臉書上聊到
-
10
从50起XR投资聊起,全球或将重回2016 VR热?_VR陀螺 从50起XR投资聊起,全球或将重回2016 VR热? 发布时间:2021-06-18 10:37 | 标签: HTC
-
7
摘要:Docker为什么火,靠的就是Docker镜像。他打包了应用程序的所有依赖,彻底解决了环境的一致性问题,重新定义了软件的交付方式,提高了生产效率。 本文分享自华为云社区《
-
11
关于容器的历史、发展以及技术本质,在互联网上已经有非常多的文章了。这里旨在结合自身的工作经验和理解,通过一系列的文章,讲清楚这项技术。关于容器的历史、发展以及技术本质,在互联网上已经有非常多的文章了。这里旨在结合自身的工作经验...
-
8
-
4
你有看过“原始建造”类型的视频吗?在这类视频中,没有任何华丽的剪辑技巧,也没有炫彩的视频渲染,只有不断劳动的人和停不下来的动作,本文作者通过分析“原始建造”类视频,向我们分享了有关现代人的厌倦与怀乡的思考,一起来看看吧。
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK