[英]Optimizing an index in a large MySQL table
我有一個大表(大約3百萬條記錄),主要包括以下字段:rowID(int),deviceID(varchar(20)),格式為1536169459(int(10))的UnixTimestamp,具有整數的powerLevel范圍介於30到90(smallint(6))之間。
我正在尋找在特定時間范圍內(使用UnixTimestamp)針對特定deviceID以及powerLevel高於特定數字的記錄。 擁有超過300萬條記錄,需要一段時間。 有沒有一種方法可以創建為此優化的索引?
在以下位置創建索引:
DeviceId,
PowerLevel,
UnixTimestamp
選擇時,您將首先縮小給定設備的記錄集,然后將其縮小到僅在正確PowerLevel范圍內的那些記錄。 最后,對於每個PowerLevel,它將通過UnixTimestamp縮小到正確的記錄。
如果我對您的理解正確,則希望加快此類查詢的速度。
SELECT something
FROM tbl
WHERE deviceID = constant
AND start <= UnixTimestamp
AND UnixTimestamp < end
AND Power >= constant
您有一個常量條件(deviceID)和兩個范圍標准(UnixTimestamp和Power)。 MySQL的索引是BTREE(按順序排序),MySQL只能對SELECT進行一次索引范圍掃描。
因此,您可能應該在(deviceID, UnixTimestamp, Power)
上選擇一個索引。 為了滿足該查詢,MySQL將隨機訪問設備ID條目的索引,然后進一步隨機訪問滿足UnixTimestamp起始條件的第一行。
然后它將順序掃描索引,並使用每個索引條目中的Power信息來決定是否應選擇每一行。
您也可以使用(deviceID, Power, UnixTimestamp)
。 但是在這種情況下,MySQL將找到匹配設備和電源標准的第一個條目,然后掃描索引以查看所有時間戳記的條目,以查看應選擇的行。
您的性能目標是讓MySQL掃描盡可能少的索引條目,因此(deviceID, UnixTimestamp, Power)
選擇似乎很有可能是更好的選擇。 UnixTimestamp上的索引列可能比Power上的索引列更具選擇性 。 (這是我的猜測。)
ALTER TABLE tbl CREATE INDEX tbl_dev_ts_pwr (deviceID, UnixTimestamp, Power);
查看Bill Karwin的教程。 另請參閱Markus Winand的https://use-the-index-luke.com
建議的三列索引僅部分有用。 優化程序將使用前兩列,但忽略第三列。
更好:
INDEX(DeviceId, PowerLevel),
INDEX(DeviceId, UnixTimestamp)
為什么?
優化器將在這兩者之間進行選擇,這似乎更具選擇性。 如果時間范圍為“ narrow”,則將使用第二個索引; 如果沒有很多具有所需PowerLevel的行,則將使用第一個索引。
更好的...
PRIMARY KEY
...您可能已將Id
作為PK? 也許(DeviceId, UnixTimestamp)
是唯一的? (或者您可以在一秒鍾內獲得單個設備的兩個讀數嗎?)如果該對是唯一的,請完全擺脫Id
並獲得
PRIMARY KEY(DeviceId, UnixTimestamp),
INDEX(DeviceId, PowerLevel)
筆記:
Id
可以節省空間,從而提供一點速度。 PRIMARY KEY(Id)
,可以確保執行彈跳。 通過將PK更改為此,可以避免跳動。 這可能會使查詢速度加倍。 另一個(次要)建議:標准化DeviceId
,以使其(可能)是2字節的SMALLINT UNSIGNED
(范圍為0..64K)而不是VARCHAR(20)
。 即使需要JOIN
,查詢也會運行得更快。 並且節省了大量空間。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.