varchar vs. timestamp
时间戳字段是类似这样的形式的:
‘2013-04-07 12:33:20.000+08’
根据iso标准,要求时间戳是精确到毫秒的,所以在秒之后有三位小数,表示毫秒,并且后缀时区(+08部分)。我们存储时间戳有很多办法,最粗糙的是字串存储,像上面那样(注意有单引号),这样一个带时区的时间戳要26个字节。而很多数据库系统里面,会用浮点数或者整数保存时间戳,通常是这样的:
4字节整数保存一个无时区无毫秒精度的时间戳,相当于19个字节的字串部分
8字节整数或者浮点数保存一个有时区有毫秒精度的是见戳,相当于26个字节的时间戳字串
所以,一个timestamp类型在数据库里头的存储大概是 4或者8字节。那么用字串呢?一般我们用 varchar,那么 varchar 的经典存储是:
4字节长度+实际数据长度
所以,字串时间戳的存储需要的空间大概是4+19或者4+26,也就是23或者30个字节。
可以看出,存储上,两者相较,差距是5~7倍。
CPU执行的速度比较
现代CPU基本都是64位的了。所以,8字节数据的比较,基本就是四次内存访问(两个八字节的数据,每次内存访问区4字节)加一次寄存器操作(把数据装入运算寄存器器)加一次寄存器比较(运算寄存器和比较寄存器进行比较)。
对于字串的23或者30个字节来说,情况就糟糕多了,因为是字串,所以基本没有什么好办法利用8字节(64位寄存器),通常都是每4字节处理一次,因此,无形之间就多了一倍的操作,而因为数据长了,这个操作更恶化:23个字节要循环访问6次内存,30个字节则是8次。所以,比8字节整数的比较,分别慢了12倍和16倍。
更详细的分析
离开CPU和内存,我们继续看看IO:同样是一千万行数据,那么8字节数据的磁盘大小是 10M * 8 = 80M,而23字节数据是 230M、30字节是300M。对应磁盘块(每块 512 字节),则分别是:80M/0.5k = 160k、230M/0.5k = 460k、300M/0.5k = 600k。字串的分别大3倍和4倍。
结论
我们把上面所有的倍数都计算一遍,会发现 timestamp 比 varchar 要快:123=36倍到164=64倍。看看我们的时间对比,20分钟=20*60s=1200s 对比 39s,大概是差距30倍,比较符合36倍的速度差的计算。
所以结论就是:能用内置的类型,就千万别用字串啊!这就是为啥当年我咆哮着冲着 qboss 的某些开发大骂的原因之一了。


