摘要:char类型字段想走索引的话,必须用引号括起来。如果是时间戳等类型的纯数字,建议还是存为int型吧。

本文分享自华为云社区《一次事故,我对MySql时间戳存char(10)还是int(10)有了全新的认识》,原文作者:奔四码农 。

美好的周五

周五的早晨,一切都是那么美好。

然而,10点多的时候,运营小哥哥突然告诉我后台打不开了,我怀着一颗“有什么大不了的,估计又是他不会连wifi”的心情,自信的打开了网址,果然,真打不开了。

这是存心让我过不好周末呀!

抓住那只bug

经过我缜密的排查,发现是一个“获取今天之前登录的用户”接口调用严重超时:

这个接口其实调用的数据表不多,在MySQL只读取了1张表,表结构如下:

获取今天之前登录的用户列表的SQL如下:

SELECT u.email, log.user_id
FROM `user` u
LEFT JOIN `log_user_active` log ON u.user_id = log.user_id
WHERE log.`log_dtime` <1634567890
LIMIT 0 , 30

这只是一个简单的SQL查询,并没有什么高精尖、复杂的查询为什么这么慢?由于log_user_active的数据量最大,所以猜想应该是log_user_active表出了问题,为了排查原因,我把SQL又简化了下,去掉了JOIN直接简化为:

SELECT log.user_id
FROM `log_user_active`
WHERE `log_dtime` <1551784072
LIMIT 0 , 30

经执行,这个语句花了将近1秒。。。如果多人同时访问,MySQL不崩溃才怪。

此时,应该确信是这个表出问题无疑了,但是字段log_dtime明明建立了索引,怎么还这么慢呢?

经过各种百度,终于发现问题所在:由于log_dtime设计的是char类型。如果想让它走索引,查询的时候,值必须要加引号,说明这是个字符串,否则是不会走索引的。我的数据恰巧都是数字组成(时间戳),查询的时候也没有刻意去加引号,导致查询的时候不走索引。

这就是问题所在了,于是进行如下尝试:

尝试1:

SQL的值加上引号

如上图,果然极快。

但是这样的话,需要改好多代码,我想想还是尝试下方法2吧。

尝试2:

果断将数据表结构log_dtime设计为INT型,如图:

再次执行SQL:

SELECT log.user_id
FROM `log_user_active`
WHERE `log_dtime` <1551784072
LIMIT 0 , 30

相应结果提升N倍:

至此,问题处理完毕。

总结

char类型字段想走索引的话,必须用引号括起来。如果是时间戳等类型的纯数字,建议还是存为int型吧。

愉快的周末,又向我招手了。

点击关注,第一时间了解华为云新鲜技术~

一次事故,我对MySQL时间戳存char(10)还是int(10)有了全新的认识的更多相关文章

  1. MySql 时间戳存char还是存int?

    一次小事故,让我对时间戳存char还是存int有了深刻的印象. 生产环境的sql条件涉及到时间戳字段的大小比较(between and),当时设计的时间戳类型是char(10),结果当数据量达到200 ...

  2. 一次线上事故,让我对MySql的时间戳存char(10)还是int(10)有了全新的认识

    美好的周五 周五的早晨,一切都是那么美好. 然鹅,10点多的时候,运营小哥哥突然告诉我后台打不开了,我怀着一颗"有什么大不了的,估计又是(S)(B)不会连wifi"的心情,自信的打 ...

  3. Mysql时间戳转Java时间戳

    MySQL 时间戳和Java返回的时间戳是不一样的 例如: 当前时间是 2014-08-04 10:42:55.204000 使用mysql时间戳函数UNIX_TIMESTAMP 返回的结果为: 14 ...

  4. mysql 字符串类型 char varchar

    字符类型用在存储名字.邮箱地址.家庭住址等描述性数据   char指的是定长字符,varchar指的是变长字符 #官网:https://dev.mysql.com/doc/refman/5.7/en/ ...

  5. Mysql的 时间戳转换 和 c# 的时间戳转换 (以秒来进行转换,非毫秒,主要是mysql不能存毫秒)

    Mysql 时间戳函数 => 从时间 转成 时间戳   UNIX_TIMESTAMP() 获取当前服务器时间的时间戳 UNIX_TIMESTAMP('2013-01-01 12:33:19') ...

  6. FROM_UNIXTIME 格式化MYSQL时间戳函数

    FROM_UNIXTIME 格式化MYSQL时间戳函数 对MYSQL没有进行过深入的研究,基础知识匮乏,一遇到问题只能手册,看来要把MYSQL的学习安排进时间表了. 函数:FROM_UNIXTIME作 ...

  7. MySQL时间戳和时间格式转换函数

    MySQL时间戳和时间格式转换函数:unix_timestamp and from_unixtime unix_timestamp将时间转化成时间戳格式.from_unixtime将时间戳转化成时间格 ...

  8. MySQL 时间戳(Timestamp)函数

    1. MySQL 获得当前时间戳函数:current_timestamp, current_timestamp() mysql> select current_timestamp, curren ...

  9. MySQL Yum存储库 安装、升级、集群

    添加MySQL Yum存储库 首先,将MySQL Yum存储库添加到系统的存储库列表中.按着这些次序: 在http://dev.mysql.com/downloads/repo/yum/上转到MySQ ...

  10. MySQL 时间戳(Timestamp)函数

    1. MySQL 获得当前时间戳函数:current_timestamp, current_timestamp() mysql> select current_timestamp, curren ...

随机推荐

  1. Django+celery+eventlet+flower+redis异步任务创建及查询实现

    1.环境版本:Django 3.2.12celery 5.3.4eventlet 0.33.3flower 2.0.1redis 3.5.3项目名称:new_project 2.celery配置(se ...

  2. 把工单历史表中的数据,按照工单进行分类,每一批工单的数据放在同一个 key 中

    /** * 把工单历史表中的数据,按照工单进行分类,每一批工单的数据放在同一个key中 * 将对象列表按名称分类成 Map(分类名必与对象的某 get 方法的后的名一致<如:get(name) ...

  3. Java8新特性(Lambda表达式、Stream流、Optional类)等

    1. Lambda表达式由来 1 package java8; 2 3 public class EmployeeTest { 4 public static void main(String[] a ...

  4. USB TYPE-C PIN定义

    USB TYPE-C 母座 USB TYPE-C 公头

  5. 关于RS485通讯TVS器件选择的经验

    先说经验结论 如果你的RS485用于频繁热拔插, 比如作为手持终端使用, 且手持器与目标板非隔离, 那么使用6.8CA可能是更好的选择. 因为有热拔插会产生浪涌, 而且在非隔离的场合有些工业设备接地也 ...

  6. 随着Web3.0的到来,IPFS能否成为未来?

    IPFS能否成为未来互联网存储市场的霸主? 首先在说IPFS之前,我们有必要先聊一聊HTTP,因为目前我们从互联网上看到的,用的,基本上都是HTTP,自从1991年发明了HTTP,到现在已经多了30多 ...

  7. Verilog HDL数据流建模与运算符

    数据流建模使用的连续赋值语句由关键词assign开始,一般用法如下: wire [位宽说明]变量名1, 变量名2, ..., 变量名n; assign 变量名 = 表达式; 只要等号右边的值发生变化, ...

  8. python之继承及其实现方法

    目录 继承 语法格式 继承的代码实现 多继承 继承 语法格式 class 子类类名(父类1, 父类2...): pass r如果一个类没有继承任何类,则默认继承object python支持多继承 定 ...

  9. Kepware楼宇自控BACnet/IP驱动

    BACnet/IP驱动是楼宇自动化设备驱动的集合,为用户提供一种方便快捷的楼宇自动化设备数采解决方案.只需要通过简单的配置就可以将常见的BACnet/IP协议设备无缝连接到 HMI/SCADA.MES ...

  10. Android OpenGL ES入门

    1.OpenGL 和OpenGL ES OpenGL(Open Graphics Library)是一种用于渲染2D和3D图形的跨平台编程接口.OpenGL提供了一套标准的函数和接口,使开发人员能够在 ...