十年網(wǎng)站開發(fā)經(jīng)驗 + 多家企業(yè)客戶 + 靠譜的建站團隊
量身定制 + 運營維護+專業(yè)推廣+無憂售后,網(wǎng)站問題一站解決
1. 執(zhí)行計劃中明明有使用到索引,為什么執(zhí)行還是這么慢?
創(chuàng)新互聯(lián)公司專注于中寧網(wǎng)站建設服務及定制,我們擁有豐富的企業(yè)做網(wǎng)站經(jīng)驗。 熱誠為您提供中寧營銷型網(wǎng)站建設,中寧網(wǎng)站制作、中寧網(wǎng)頁設計、中寧網(wǎng)站官網(wǎng)定制、成都小程序開發(fā)服務,打造中寧網(wǎng)絡公司原創(chuàng)品牌,更為您提供中寧網(wǎng)站排名全網(wǎng)營銷落地服務。
2. 執(zhí)行計劃中顯示掃描行數(shù)為 644,為什么 slow log 中顯示 100 多萬行?
a. 我們先看執(zhí)行計劃,選擇的索引 “INDX_BIOM_ELOCK_TASK3(TASK_ID)”。結合 sql 來看,因為有 "ORDER BY TASK_ID DESC" 子句,排序通常很慢,如果使用了文件排序性能會更差,優(yōu)化器選擇這個索引避免了排序。
那為什么不選 possible_keys:INDX_BIOM_ELOCK_TASK 呢?原因也很簡單,TASK_DATE 字段區(qū)分度太低了,走這個索引需要掃描的行數(shù)很大,而且還要進行額外的排序,優(yōu)化器綜合判斷代價更大,所以就不選這個索引了。不過如果我們強制選擇這個索引(用 force index 語法),會看到 SQL 執(zhí)行速度更快少于 10s,那是因為優(yōu)化器基于代價的原則并不等價于執(zhí)行速度的快慢;
b. 再看執(zhí)行計劃中的 type:index,"index" 代表 “全索引掃描”,其實和全表掃描差不多,只是掃描的時候是按照索引次序進行而不是行,主要優(yōu)點就是避免了排序,但是開銷仍然非常大。
Extra:Using where 也意味著掃描完索引后還需要回表進行篩選。一般來說,得保證 type 至少達到 range 級別,最好能達到 ref。
在第 2 點中提到的“慢日志記錄Rows_examined: 1161559,看起來是全表掃描”,這里更正為“全索引掃描”,掃描行數(shù)確實等于表的行數(shù);
c. 關于執(zhí)行計劃中:“rows:644”,其實這個只是估算值,并不準確,我們分析慢 SQL 時判斷準確的掃描行數(shù)應該以 slow log 中的 Rows_examined 為準。
4. 優(yōu)化建議:添加組合索引 IDX_REL_DEVID_TASK_ID(REL_DEVID,TASK_ID)
優(yōu)化過程:
TASK_DATE 字段存在索引,但是選擇度很低,優(yōu)化器不會走這個索引,建議后續(xù)可以刪除這個索引:
select count(*),count(distinct TASK_DATE) from T_BIOMA_ELOCK_TASK;+------------+---------------------------+| count(*) | count(distinct TASK_DATE) |+------------+---------------------------+| 1161559 | 223 |+------------+---------------------------+
在這個 sql 中 REL_DEVID 字段從命名上看選擇度較高,通過下面 sql 來檢驗確實如此:
select count(*),count(distinct REL_DEVID) from T_BIOMA_ELOCK_TASK;+----------+---------------------------+| count(*) | count(distinct REL_DEVID) |+----------+---------------------------+| 1161559 | 62235 |+----------+---------------------------+
由于有排序,所以得把 task_id 也加入到新建的索引中,REL_DEVID,task_id 組合選擇度 100%:
select count(*),count(distinct REL_DEVID,task_id) from T_BIOMA_ELOCK_TASK;+----------+-----------------------------------+| count(*) | count(distinct REL_DEVID,task_id) |+----------+-----------------------------------+| 1161559 | 1161559 |+----------+-----------------------------------+
在測試環(huán)境添加 REL_DEVID,TASK_ID 組合索引,測試 sql 性能:alter table T_BIOMA_ELOCK_TASK add index idx_REL_DEVID_TASK_ID(REL_DEVID,TASK_ID);
添加索引后執(zhí)行計劃:
這里還要注意一點“隱式轉(zhuǎn)換”:REL_DEVID 字段數(shù)據(jù)類型為 varchar,需要在 sql 中加引號:AND T.REL_DEVID = 000000025xxx AND T.REL_DEVID = '000000025xxx'
執(zhí)行時間從 10s+ 降到 毫秒級別:
1 row in set (0.00 sec)
結論
一個典型的 order by 查詢的優(yōu)化,添加更合適的索引可以避免性能問題:執(zhí)行計劃使用索引并不意味著就能執(zhí)行快。
這應該是時間戳 SELECT DATEADD(S,1408579200000/1000.0 + 8*3600,'1970-01-01 00:00:00') 這樣換算成時間
Datetime類型只能顯示秒,需要轉(zhuǎn)換;
轉(zhuǎn)換SQL 語句如下:
select?convert(varchar(23),getdate(),121)
執(zhí)行SQL 得出的結果如下:
2015-07-31 17:48:40.083
???
時間戳格式?
SELECT?CAST('2014-01-01'?AS?TIMESTAMP)
要這樣的?
毫秒格式是什么意思。如果是datetime類型的字段,可以用convert函數(shù),例如
select convert(varchar(50),getdate(),120)
結果是2012-03-22 12:53:19
1:在數(shù)據(jù)庫A創(chuàng)建DBLINK
2:在數(shù)據(jù)庫A創(chuàng)建臨時表zxx_excute_time統(tǒng)計時間
3:在數(shù)據(jù)庫B創(chuàng)建多個核心業(yè)務表結構
4:在在數(shù)據(jù)庫A創(chuàng)建統(tǒng)計SQL執(zhí)行時間的存儲過程
5:單獨測試核心表單獨測試
6:同時插入多個核心表數(shù)據(jù)
注意:盡量使用核心表測試,因為核心包含lob字段。
SQL插入速度受帶寬IO影響,如果帶寬中存在大量的lob字段,那么可能嚴重影響到寫性能。