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

摘要:char類型字段想走索引的話,必須用引號括起來。若是是時間戳等類型的純數字,建議仍是存爲int型吧。

本文分享自華爲雲社區《一次事故,我對MySql時間戳存char(10)仍是int(10)有了全新的認識》,原文做者:奔四碼農 。segmentfault

美好的週五

週五的早晨,一切都是那麼美好。
image.pngspa

然而,10點多的時候,運營小哥哥忽然告訴我後臺打不開了,我懷着一顆「有什麼大不了的,估計又是他不會連wifi」的心情,自信的打開了網址,果真,真打不開了。
image.png設計

這是存心讓我過很差週末呀!code

抓住那隻bug

通過我縝密的排查,發現是一個「獲取今天以前登陸的用戶」接口調用嚴重超時:
image.pngblog

這個接口其實調用的數據表很少,在MySQL只讀取了1張表,表結構以下:
image.png索引

獲取今天以前登陸的用戶列表的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不崩潰纔怪。
image.pngget

此時,應該確信是這個表出問題無疑了,可是字段log_dtime明明創建了索引,怎麼還這麼慢呢?it

通過各類百度,終於發現問題所在:因爲log_dtime設計的是char類型。若是想讓它走索引,查詢的時候,值必需要加引號,說明這是個字符串,不然是不會走索引的。個人數據恰巧都是數字組成(時間戳),查詢的時候也沒有刻意去加引號,致使查詢的時候不走索引。

這就是問題所在了,因而進行以下嘗試:

嘗試1:

SQL的值加上引號
image.png

如上圖,果真極快。

可是這樣的話,須要改好多代碼,我想一想仍是嘗試下方法2吧。

嘗試2:

果斷將數據表結構log_dtime設計爲INT型,如圖:
image.png

再次執行SQL:

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

相應結果提高N倍:
image.png

至此,問題處理完畢。

總結

char類型字段想走索引的話,必須用引號括起來。若是是時間戳等類型的純數字,建議仍是存爲int型吧。
image.png

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

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

相關文章
相關標籤/搜索