MySQL中存储时间的最佳实践指南


Posted in MySQL onJuly 01, 2021
目录
  • 前言
  • 不要使用字符串存储时间类型
  • MySQL 中的日期类型
    • DATETIME
    • TIMESTAMEP
    • TIMESTAMP 的性能问题
    • 数值型时间戳(INT)
    • DATETIME vs TIMESTAMP vs INT,怎么选?
  • 总结

前言

平时开发中经常需要记录时间,比如用于记录某条记录的创建时间以及修改时间。在数据库中存储时间的方式有很多种,比如 MySQL 本身就提供了日期类型,比如 DATETIME,TIMESTAMEP 等,我们也可以直接存储时间戳为 INT 类型,也有人直接将时间存储为字符串类型。

那么到底哪种存储时间的方式更好呢?

不要使用字符串存储时间类型

这是初学者很容易犯的错误,容易直接将字段设置为 VARCHAR 类型,存储"2021-01-01 00:00:00"这样的字符串。当然这样做的优点是比较简单,上手快。

但是极力不推荐这样做,因为这样做有两个比较大的问题:

  • 字符串占用的空间大
  • 这样存储的字段比较效率太低,只能逐个字符比较,无法使用 MySQL 提供的日期API

MySQL 中的日期类型

MySQL 数据库中常见的日期类型有 YEAR、DATE、TIME、DATETIME、TIMESTAMEP。因为一般都需要将日期精确到秒,其中比较合适的有DATETIME,TIMESTAMEP。

DATETIME

DATETIME 在数据库中存储的形式为:YYYY-MM-DD HH:MM:SS,固定占用 8 个字节。

从 MySQL 5.6 版本开始,DATETIME 类型支持毫秒,DATETIME(N) 中的 N 表示毫秒的精度。例如,DATETIME(6) 表示可以存储 6 位的毫秒值。

TIMESTAMEP

TIMESTAMP 实际存储的内容为‘1970-01-01 00:00:00'到现在的毫秒数。在 MySQL 中,由于类型 TIMESTAMP 占用 4 个字节,因此其存储的时间上限只能到‘2038-01-19 03:14:07'。

从 MySQL 5.6 版本开始,类型 TIMESTAMP 也能支持毫秒。与 DATETIME 不同的是,若带有毫秒时,类型 TIMESTAMP 占用 7 个字节,而 DATETIME 无论是否存储毫秒信息,都占用 8 个字节。

类型 TIMESTAMP 最大的优点是可以带有时区属性,因为它本质上是从毫秒转化而来。如果你的业务需要对应不同的国家时区,那么类型 TIMESTAMP 是一种不错的选择。比如新闻类的业务,通常用户想知道这篇新闻发布时对应的自己国家时间,那么 TIMESTAMP 是一种选择。Timestamp 类型字段的值会随着服务器时区的变化而变化,自动换算成相应的时间,说简单点就是在不同时区,查询到同一个条记录此字段的值会不一样。

TIMESTAMP 的性能问题

TIMESTAMP 还存在潜在的性能问题。

虽然从毫秒数转换到类型 TIMESTAMP 本身需要的 CPU 指令并不多,这并不会带来直接的性能问题。但是如果使用默认的操作系统时区,则每次通过时区计算时间时,要调用操作系统底层系统函数 __tz_convert(),而这个函数需要额外的加锁操作,以确保这时操作系统时区没有修改。所以,当大规模并发访问时,由于热点资源竞争,会产生两个问题:

  • 性能不如 DATETIME:DATETIME 不存在时区转化问题。
  • 性能抖动:海量并发时,存在性能抖动问题。

为了优化 TIMESTAMP 的使用,建议使用显式的时区,而不是操作系统时区。比如在配置文件中显示地设置时区,而不要使用系统时区:

[mysqld]

time_zone = "+08:00"

简单总结一下这两种数据类型的优缺点:

  • DATETIME 没有存储的时间上限,而TIMESTAMP存储的时间上限只能到‘2038-01-19 03:14:07'
  • DATETIME 不带时区属性,需要前端或者服务端处理,但是仅从数据库保存数据和读取数据而言,性能更好
  • TIMESTAMP 带有时区属性,但是每次需要通过时区计算时间,并发访问时会有性能问题
  • 存储 DATETIME 比 TIMESTAMEP 多占用一部分空间

数值型时间戳(INT)

很多时候,我们也会使用 int 或者 bigint 类型的数值也就是时间戳来表示时间。

这种存储方式的具有 Timestamp 类型的所具有一些优点,并且使用它的进行日期排序以及对比等操作的效率会更高,跨系统也很方便,毕竟只是存放的数值。缺点也很明显,就是数据的可读性太差了,你无法直观的看到具体时间。

如果需要查看某个时间段内的数据

select * from t where created_at > UNIX_TIMESTAMP('2021-01-01 00:00:00');

DATETIME vs TIMESTAMP vs INT,怎么选?

每种方式都有各自的优势,下面再对这三种方式做一个简单的对比:

 

日期类型 占用空间 日期格式 日期范围 是否存在时区问题
DATETIME 8 字节 YYYY-MM-DD HH:MM:SS 1000-01-01 00:00:00 ~9999-12-31 23:59:59
TIMESTAMP 4 字节 YYYY-MM-DD HH:MM:SS 1970-01-01 00:00:00 ~2038-01-19 03:14:07
INT 4 字节 全数字时间戳 1000-01-01 00:00:01 之后的时间

TIMESTAMP 与 INT 本质一样,但是相比而言虽然 INT 对开发友好,但是对 DBA 以及数据分析人员不友好,可读性差。所以《高性能 MySQL 》的作者推荐  TIMESTAMP 的原因就是它的数值表示时间更加直观。下面是原文:

MySQL中存储时间的最佳实践指南

至于时区问题,可以由前端或者服务这里做一次转化,不一定非要在数据库中解决。

总结

本文比较了几种最常使用的存储时间的方式,我最推荐的还是 DATETIME。理由如下:

  • TIMESTAMP 比数值型时间戳可读性更好
  • DATETIME 的存储上限为 9999-12-31 23:59:59,如果使用 TIMESTAMP,则 2038 年需要考虑解决方案
  • DATETIME 由于不需要时区转换,所以性能比 TIMESTAMP 好
  • 如果需要将时间存储到毫秒,TIMESTAMP 要 7 个字节,和 DATETIME 8 字节差不太多

到此这篇关于MySQL中存储时间的文章就介绍到这了,更多相关MySQL存储时间内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

MySQL 相关文章推荐
mysql 8.0.24 安装配置方法图文教程
May 12 MySQL
MySQL主从搭建(多主一从)的实现思路与步骤
May 13 MySQL
解决Navicat for MySQL 连接 MySQL 报2005错误的问题
May 29 MySQL
一文读懂navicat for mysql基础知识
May 31 MySQL
详解MySQL中的pid与socket
Jun 15 MySQL
MySQL如何使用使用Xtrabackup进行备份和恢复
Jun 21 MySQL
mysql的数据压缩性能对比详情
Nov 07 MySQL
面试被问select......for update会锁表还是锁行
Nov 11 MySQL
教你使用VS Code的MySQL扩展管理数据库的方法
Jan 22 MySQL
一文弄懂MySQL索引创建原则
Feb 28 MySQL
一次Mysql update sql不当引起的生产故障记录
Apr 01 MySQL
手把手带你彻底卸载MySQL数据库
Jun 14 MySQL
MySQL连表查询分组去重的实现示例
Jul 01 #MySQL
python中的mysql数据库LIKE操作符详解
Jul 01 #MySQL
解决Mysql的left join无效及使用的注意事项说明
mysql left join快速转inner join的过程
MySQL 十大常用字符串函数详解
Mysql中调试存储过程最简单的方法
Jun 30 #MySQL
mysql如何配置白名单访问
Jun 30 #MySQL
You might like
一些操作和快捷键的理解和讨论
2020/03/04 星际争霸
Drupal7连接多个数据库及常见问题解决
2014/03/02 PHP
PH P5.2至5.5、5.6的新增功能详解
2014/07/14 PHP
PHP获取用户客户端真实IP的解决方案
2016/10/10 PHP
php实现文件上传及头像预览功能
2017/01/15 PHP
JavaScript动态调整TextArea高度的代码
2010/12/28 Javascript
输入框的字数时时统计—关于 onpropertychange 和 oninput 使用
2011/10/21 Javascript
JQuery入门—编写一个简单的JQuery应用案例
2013/01/03 Javascript
一个简单的jQuery计算器实现了连续计算功能
2014/07/21 Javascript
JavaScript字符串对象toLowerCase方法入门实例(用于把字母转换为小写)
2014/10/17 Javascript
jquery+正则实现统一的表单验证
2015/09/20 Javascript
jquery UI Datepicker时间控件的使用及问题解决
2016/04/28 Javascript
用js实现放大镜的效果的简单实例
2016/05/23 Javascript
无缝滚动的简单实现代码(推荐)
2016/06/07 Javascript
AngularJS深入探讨scope,继承结构,事件系统和生命周期
2016/11/02 Javascript
基于JQuery和原生JavaScript实现网页定位导航特效
2017/04/03 jQuery
angular中实现控制器之间传递参数的方式
2017/04/24 Javascript
动态统计当前输入内容的字节、字符数的实例详解
2017/10/27 Javascript
Vue 处理表单input单行文本框的实例代码
2019/05/09 Javascript
JS块级作用域和私有变量实例分析
2019/05/11 Javascript
世界上最短的数字判断js代码
2019/09/09 Javascript
使用konva和vue-konva库实现拖拽滑块验证功能
2020/04/27 Javascript
python单例模式的多种实现方法
2019/07/26 Python
python+Django实现防止SQL注入的办法
2019/10/31 Python
python2 对excel表格操作完整示例
2020/02/23 Python
Python基于argparse与ConfigParser库进行入参解析与ini parser
2021/02/02 Python
欧洲最大的球衣网上商店:Kitbag
2017/11/11 全球购物
护理专业大学生自我推荐信
2014/01/25 职场文书
2014年两会学习心得范例
2014/03/17 职场文书
统计专业自荐书
2014/07/06 职场文书
2015年社区计生工作总结
2015/04/21 职场文书
2015年机关纠风工作总结
2015/05/15 职场文书
小学三年级班主任工作经验交流材料
2015/11/02 职场文书
Django项目配置Memcached和Redis, 缓存选择哪个更有优势
2021/04/06 Python
python图片灰度化处理的几种方法
2021/06/23 Python
Android Studio实现简易进制转换计算器
2022/05/20 Java/Android