摘要:char類型字段想走索引的話,必須用引号括起來。如果是時間戳等類型的純數字,建議還是存為int型吧。
本文分享自華為雲社群《一次事故,我對MySql時間戳存char(10)還是int(10)有了全新的認識》,原文作者:奔四碼農 。
美好的周五
周五的早晨,一切都是那麼美好。
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicGcq5ydwIzNfVmYwI2YhVmN5QjN0ITN5ImZ3QzNwImNyQWM2kzYzYmMtIjdvwFM48CXt92YucWbphmeuMzYpB3Lc9CX6MHc0RHaiojIsJye.jpg)
然而,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型吧。
愉快的周末,又向我招手了。
點選關注,第一時間了解華為雲新鮮技術~