SELECT
recordTime,
IFNULL(FORMAT(windSpeed_10mA,2),"NAN") AS WS10,
IFNULL(FORMAT(windSpeed_30m,2),"NAN") AS WS30,
IFNULL(FORMAT(windSpeed_50m,2),"NAN") AS WS50,
IFNULL(FORMAT(windSpeed_95mA,2),"NAN") AS WS95A,
IFNULL(FORMAT(windSpeed_95mB,2),"NAN") AS WS95B,
IFNULL(FORMAT(windDirection_10mA,1),"NAN") AS WD10,
IFNULL(FORMAT(windDirection_30m,1),"NAN") AS WD30,
IFNULL(FORMAT(windDirection_50m,1),"NAN") AS WD50,
IFNULL(FORMAT(windDirection_95m,1),"NAN") AS WD95
FROM
wind_Raw
WHERE
recordTime BETWEEN '2017-12-01 00:00:01' AND '2017-12-29 00:00:00'
ORDER BY
recordTime
#wind_Raw資料表簡述:記錄每秒的風速、風向變化。一日計有8萬6千400筆資料。
上面這串 SELECT 查詢指令,耗時了 210 秒才得到查詢結果。
若是將 recordTime 的結束時間改為 '2017-12-28 00:00:00'(少一天),只要耗時15秒就可以得到結果。
所以我利用了 EXPLAIN 來分析這兩串 SQL 的差別,結果如下:
28 天的 EXPLAIN 分析結果:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE wind_Raw range PRIMARY,recordTime,recordTime_2,recordTime_3,recor... PRIMARY 60 NULL 2011148 Using where
29 天的 EXPLAIN 分析結果:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE wind_Raw ALL PRIMARY,recordTime,recordTime_2,recordTime_3,recordTime_4 NULL NULL NULL 10761191 Using where; Using filesort
多查詢了一天的資料量,就會造成 MySQL 採用了不一樣的方式來處理。且29天還是採用耗時很高的全表掃描…
針對這個問題,不知道是否有資料庫高手可提供意見進行改善?
會不會是 你有啟動 query cache, 當你 先query 29天時候 已經先cache 了部分結果。
所以當你跑第二次,只query 28天時候, cache 就倒出來用了。
多執行幾次 結果都是一樣嗎?
您好
根據我之前自己的測試(資料量大約60萬筆以上)
強烈建議 不要用datetime 作 index 或是搜尋條件
datetime的索引效果很差
建議 根據蒐尋的方式來拆開欄位
我自己是拆開程 date 跟 time ,這樣我要搜尋某一天的資料時 速度會快很多
我的表格資料量一天是新增8萬6400筆(一天的秒數),預計要一次 SQL 要查詢 31 天的量。
其實我實測起來,datetime 的 Primary Key 索引效果並不差~
任何一天的資料,甚至28天的區間,都可以快速查詢到~(phpMyAdmin的查詢顯示只要0.6秒就完成了,只是畫面顯示要稍微等待一下)
雖然拆開為 date 和 time,再組成 Primary Key 形成雙欄位的索引也是一個好方法,但實際上我也是害怕超過 29 天的量後,就又回到原本的問題。且單索引就已造成 MySQL 作出詭異的檔案處理決策,我想換成雙索引則有更的高機率發生。
其實在我的案例中,索引的設計上並非大問題~
反而是 MySQL 面對某一程度的大數據時,所要作的資料處理決策差異,才是引發這個問題的主因。
也就是說不知道為什麼:「一樣的SQL,只是多了8萬的資量料,卻會造成 MySQL 放棄以鎖定資料範圍的方式進行索引查詢。反而去採用全表格的非索引搜尋?」
註:此 SQL 若不加 Order By 子句,則28、29天都是採用鎖定資料範圍的索引搜尋。回傳結果極為快速的。
當然這是要看你的使用需求,我是航班搜尋,資料量 每個table 上千萬筆,每次都是拉出特定航線一天的資料,所以把date time 拆開會有明顯效果
另外 看你的需求是每次要處理一個月份的資料,我自己的做法是,Log 表 跟 結果顯示表 分開,log的資料每天一次撈出來處理後 塞進結果顯示報表,資料再每天固定處理一次,顯示的人 何時看都可以
當然這要看你如何顯示資料
假設每天處理一次把資料量從八萬筆 變成一筆,這樣 資料量會大幅縮減成一個月28~31筆
以我們的狀況也有是作到資料精簡化的需求~
只不過,我們是把秒原始資料另計成 10 分鐘統計資料~
利用這些 10 分鐘統計資料來顯示日、月、年報的話,原則上並不會有系統壓力出現~
同時,秒資料並不開放使用者搜尋與使用的~
但因為我們目前在需求上有固定將一月份的秒資料匯出成 txt 檔的情況。
在進行這種一次性的大量資料匯出時,無意間發現資料庫系統有這樣子的特性,所以正在想辦法優化這部份的問題~
就我目前最新測試結果,無論 28 天或 29 天,如果只有 SELECT recrodTime 這個 Primary Key 欄位,就算都有加 ORDER BY 子句,兩者 MySQL 一樣會採用索引的方式進行查詢。
但此 SELECT 只要另加入一個非 Primary Key 的欄位上去,就如同原 PO 的內容,MySQL 對於 29 天的是採用非索引式的全表格搜尋,並再作 filesort 的動作。28 的則不會。
所以我到現在還是搞不清楚 MySQL 進行決策的判斷點何在?