2014-10-20 80 views
1

我想優化我的MySQL數據庫,以便儘可能快地查詢它。需要關於如何索引和優化特定MySQL數據庫的建議

它是這樣的:

我的DB由1臺具有(現在)約18萬行的 - 而迅速增長。 此表格包含以下列 - idx,time,tag_id,x,y,z。 沒有列有任何空值。

'idx'是INT(11)索引列,AI和PK。現在它按升序排列。

「時間」是日期時間列。它也是上升的。表格中「時間」值的50%是不同的(其餘值將最多出現兩次或三次)。

'tag_id'是一個INT(11)列。它沒有以任何方式排序,並且有30-100個不同的可能tag_id值遍佈整個數據庫。這也是另一個表的外鍵。

INSERT - 每隔2-3秒將一個新行插入表中。 'idx'由服務器(AI)計算。由於「時間」列表示插入行的時間,因此插入的每個新「時間」將高於或等於上一行。所有其他列值都沒有任何順序。

SELECT - 這裏是一個典型查詢的例子: 「select x,y,z,time from table where'date'(time)between'2014-08-01'and'2014-10-01'and tag_id = 123456「

因此,'time'和'tag_id'是出現在where部分的唯一列,並且他們兩個總會出現在每個查詢的where部分。 'x','y'和'z'和'時間'將一直出現在選擇部分。 'tag_id'有時也可能出現在選擇部分。

查詢通常會尋找更高(更近)的時間,而不是更老的時間。意思 - 表中後面的行將被搜索更多。

INDEXES- 現在,作爲PK的'idx'是聚集的ASC索引。 '時間'也有一個非集羣的ASC索引。

就是這樣。考慮到所有這些數據,典型的查詢將在30秒內返回結果。我試圖降低這個時間。任何建議?

我在考慮將一個或兩個索引從ASC更改爲DESC(因爲更高的值在搜索中更受歡迎)。如果我將'idx'更改爲DESC,它將在物理上顛倒整個表格。如果我將「時間」更改爲DESC,它將會顛倒「時間」索引樹。但由於這是一個1800萬行的表,因此這樣的更改可能需要很長時間才能完成,所以我想確保這是一個好主意。問題是,如果我顛倒了順序並插入了一個新行,服務器是否知道將它快速放置在表的開頭?或者每次都會在這張桌子上搜索這個地方?並且會在表格的開頭部分添加新的一行意味着每次都需要對整個表格進行某種數據轉換?

或者我只是需要一個不同的索引技術? 你有任何想法非常歡迎..謝謝!

+0

[https://gist.github.com/gilad905/bd30b5c3e5dd8c0165fc47c173ac0a54](一些調試工具) – 2017-08-22 15:20:56

回答

1
select x, y, z, time from table 
where date(time) between '2014-08-01' and '2014-10-01' and tag_id = 123456 

把一列的函數調用等date(time)內部敗壞使用索引該列的任何機會。如果您想使用索引,則必須僅使用裸列進行比較。

所以,如果你想比較它的日期,你應該存儲一個DATE列。如果你有一個DATETIME列,你可能不得不使用一個搜索詞是這樣的:

WHERE `time` >= '2014-08-01 00:00:00 AND `time` < '2014-10-02 00:00:00' ... 

此外,你應該在那裏你可以使用多列索引。首先在等條件中使用列,然後在範圍條件中使用一列。有關此規則的更多信息,請參閱我的演示文稿How to Design Indexes, Really

您也可以從添加不用於搜索的列中受益,以便查詢可以從索引條目中單獨檢索列。將這些列放在用於搜索或排序的列之後。這被稱爲僅索引查詢。

因此,對於這個問題時,你指標應該是:

ALTER TABLE `this_table` ADD INDEX (tag_id, `time`, x, y, z); 

關於ASC與DESC,語法支持不同方向的索引選項,但在MySQL中使用的兩種最流行的存儲引擎,InnoDB和MyISAM,沒有區別。排序的任何一個方向都可以或多或少地使用任何一種類型的索引。

+0

謝謝!!我會檢查你的建議 – 2014-10-21 10:17:18

+0

非常感謝Bill!我按照你所說的將00:00:00添加到時間查詢中,並且它完美地工作! – 2014-10-22 16:10:00

+0

很高興幫助!順便說一句,在StackOverflow中,習慣上給予有幫助的答案upvote或檢查「已接受的答案」按鈕以獲得最有幫助的答案。 – 2014-10-22 16:24:06