一次事故,我對MySQL時間戳存char(10)還是int(10)有了全新的認識


摘要: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型吧。

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

 

點擊關注,第一時間了解華為雲新鮮技術~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM