突然有开发人员问我,使用 varchar 来存储日期,索引查询效率上的区别。
oracle 中date 类型固定使用7个字节
mysql 中 date 类型使用3个字节,datetime使用8个字节(DATETIME的打包效率更高,对非分数部分需要5个而不是8个字节,并且所有三个部分都有一个小数部分,需要0到3个字节,具体取决于存储值的小数秒精度)
可以看出使用日期格式存储,比直接使用字符串存储使用的字节数要少(更省空间)
下面在oracle 中进行测试,测试的数据量级为 1亿6千万行数据,2列,日期列上有索引
因为列比较少,所以索引大小几乎和表大小一致。
理论上使用日期格式是要比字符串存储效率要高的,具体在查询中有多大的提升,下面用实践来检验。
测试日期字符串自动截断不包含时分秒,类似'07-MAR-19',9个字符
1千万行数据下,经过测试,范围查询,唯一查询,2者使用的时间差不多,几乎没有差别
在存储空间上,使用date类型要少30M,加上索引的空间,总共节省大约60M的存储空间。
结论1:在千万级别数据量下,几乎没有差别。
然后讲数据量量级巨大化,提升到亿级别,1亿6千万行数据(翻16倍)
--表大小相差400M,索引大小相差2G(非叶子节点块急剧增加),1表4G,2表6G
查询效率情况
索引范围扫描 60万行,查询效率基本没有差别
结论2: 在使用索引的情况下,等量的少部分范围扫描没有差别。
使用full index scan
扫描所有索引块的情况下。
SELECT /*+ index(tmp_test1 IDX_TMP_TEST1) */ count(insert_time) FROM tmp_test1;
执行时间为 5分36秒
字符串索引的扫描情况:
select /*+ index(tmp_test2 IDX_TMP_TEST2) */ count(insert_time) from tmp_test2;
执行时间为10分04秒
结论3:
在全索引扫描情况下,由于扫描的数据块有差别,导致字符串索引耗时更长(这个其实影响也和I/O效率有关,I/O越强,影响越小)