mysql強制使用索引
在公司后台某模塊功能記錄日志中有一個搜索功能,通過前段時間的產品使用時間區間進行搜索反饋有些卡頓,我發現這個搜索功能比較慢,要3秒左右才能出來,就決定對這里做一下優化。
通過分析代碼和SQL發現最核心的問題在於一個區間查詢耗時太長,耗時2秒多,所以我決定看看這里能不能優化,其中核心SQL為
SELECT * FROM XXX_kcb WHERE (`rktime` BETWEEN '2017-09-11 09:34:13' AND '2017-10-11 09:34:13') and xh > 27851 AND column1 = 'xxx' AND (column2 = 'null' OR LENGTH(column2) > 10) ORDER BY xh DESC LIMIT 0, 30
這個查詢是一個簡單查詢,沒有聯表,就是單表的limit分頁查詢,外加一個時間區間和字段搜索,我通過SQL分析 explain 發現並未走索引,掃描區間也很大,由於該表擁有接近100萬的記錄,查詢的掃描區間接近50萬,我感覺這樣肯定是效率不高的。
然后查詢了一下數據,發現耗時確實在2.6秒左右,我起初的設想是,column2字段查詢肯定是沒法改了 ,畢竟那涉及到以前的業務,該字段這樣搜索查詢確實有違常理,但是既然之前的功能已經這樣設計了,現在去做調整,反而有可能有問題,那么就只有在 xh rktime column1下手了,xh它寫死了,定了某條記錄開始進行查詢,我猜測可能之前的數據是測試數據或者是廢棄數據,那既然有個標尺,就不去動它,column1是固定的查詢值,這樣也沒法改,這樣的固定值在數據行中差異不明顯,加索引效果也不大,然后是rktime了,唯一能動文章的也只有它了。
然后我好好分析了一下這個模塊要實現的功能邏輯,就是查詢這段時間內符合要求的數據,這段時間,很明顯是一個月,能不能設定這個查詢區間只能查一個星期呢?
我改為一周內的時間區間查詢,肯定能降低查詢的查詢區間啊,然而令人遺憾的是,這個降低查詢區間間隔,並沒有多大效果,最后無奈,我給ctime添加了一個 normal index btree索引,加了索引后,我本以為一切都會好起來,誰知,explain后效果還是那樣!
可能用到的索引keys 主鍵 ctime ,然而呢 查詢區間還是接近45萬,效果並不明顯,查詢時間也還是2秒多,這可讓我犯難了,一時束手無策,思考許久,突然想到這感覺是索引沒有真正生效導致的,那么能不能強制告訴mysql使用某個索引了,讓他主動是走某個索引,然后我查詢了資料 找到了force index(強制要走的那個索引) ,我馬上就試了一下
SELECT * FROM XXX_kcb force index(rktime) WHERE (`rktime` BETWEEN '2017-09-11 09:34:13' AND '2017-10-11 09:34:13') and xh > 27851 AND column1 = 'xxx' AND (column2 = 'null' OR LENGTH(column2) > 10) ORDER BY xh DESC LIMIT 0, 30
果然 explain分析之后 使用了ctime索引
而且查詢區間降低到3萬多了,這個效果太明顯了,耗時降低到0.2秒左右,然后這個功能馬上從3秒才能打開降低到0.3秒就能打開了,這個優化效果令我非常滿意。
在和運維討論該表的數據時,運維提供方案說,看到該表數據量龐大 接近100萬,並且時間很多是2015年 2016年的,他提出可以轉移2015年 2016年的數據,我查看了一下,2015年和2016年的數據合計起來有70多萬了,占據了絕大部分,如果轉移的話,確實有利於我們查詢啊,比對啊,更新啊之類的,因為這是一張日志表,在某個期間具有時效性,畢竟大部分時候今年不會再看去年前年的查詢數據了,所以我覺得這種做法也有依據,也合理,恰逢同事請假休息,此事等他回來再做討論。
本次想到強制使用索引,也是靈光一現,稍微有一些運氣在里面的,不然還真不好解決這個問題,算是天公作美吧!