2012-07-27 56 views
1

我有2千萬條記錄的mysql表Stop_Times。分區MySQL表後創建索引?

我對此表使用MyISAM存儲引擎。

我的表結構

| agency_id   | varchar(50) | NO |  | NULL |  | 
| trip_id    | varchar(50) | NO | PRI | NULL |  | 
| arrival_time  | time  | NO |  | NULL |  | 
| departure_time  | time  | NO |  | NULL |  | 
| stop_id    | varchar(50) | NO | PRI | NULL |  | 
| stop_sequence  | int(11)  | NO | PRI | NULL |  | 
| route_id   | varchar(50) | NO |  | NULL |  | 
| route_type   | int(5)  | NO |  | NULL |  | 
+---------------------+-------------+------+-----+-------- 

顯示創建表Stop_Times的輸出爲 -

CREATE TABLE `Stop_Times` (
`agency_id` varchar(50) NOT NULL, 
`trip_id` varchar(50) NOT NULL, 
`arrival_time` time NOT NULL, 
`departure_time` time NOT NULL, 
`stop_id` varchar(50) NOT NULL, 
`stop_sequence` int(11) NOT NULL, 
`route_id` varchar(50) NOT NULL, 
`route_type` int(5) NOT NULL, 
UNIQUE KEY `idx_Stop_Times` (`agency_id`,`trip_id`,`stop_sequence`,`stop_id`) 
) ENGINE=MyISAM DEFAULT CHARSET=utf8 
/*!50100 PARTITION BY KEY (stop_id) 
PARTITIONS 250 */ 

我有一個查詢

select distinct trip_id, stop_sequence from Stop_Times where agency_id = ? and stop_id = ? 

分區表此查詢之前花了4-5分鐘。

但現在我已經分區上表stop_id像以key(stop_id) 分區

現在這個查詢花費2-3秒來執行。

我有另一個查詢接着上述查詢 -

select distinct(stop_id) from Stop_Times where agency_id = ? and trip_id = ? and stop_sequence > ? 

輸出上上述查詢解釋是 -

1 SIMPLE Stop_Times range idx_Stop_Times idx_Stop_Times 308 NULL 250 Using where; Using index; Using temporary 

此查詢花費更多的時間90 - 150秒。

所以我的問題是我需要在trip_id和stop_sequence上創建索引嗎? 這會加快查詢性能嗎?

我是否需要從InnoDB的MyISAM中更改存儲引擎,因爲此表有多次來自多個用戶的讀取(選擇查詢)?

請數據庫大師幫幫我。

謝謝

回答

1

(agency_id, trip_id, stop_sequence, stop_id)創建一個覆蓋索引。請注意,索引中列的順序很重要。使用不同的順序可能效率較低。

+0

謝謝馬克的回覆。我將按給定的順序創建一個索引。但是,由於表上的讀取次數,我是否需要更改存儲引擎? – Deepu 2012-07-27 07:11:44

+0

我不認爲你需要改變引擎。在添加索引後您獲得了哪些性能? – 2012-07-27 07:24:36

+0

嗨馬克我已經創建了索引,第二個查詢需要約30秒。我認爲執行查詢也太多了。 – Deepu 2012-07-27 08:02:30

1

也許你想考慮分解這個數據集。

我維護一個名爲Shard-Query的工具,它可以並行查詢的所有分片。您有一個自然分片鍵(stop_id),您正在使用它來進行KEY分區。使用Shard-Query,您可以使用HASH分區的相同列,以便您獲得功能等同性。

使用Shard-Query,您將創建250個數據庫,每個數據庫都具有相同的表副本。這相當於你的250個分區。

分區消除
當你執行的第一個查詢,碎片查詢將查詢發送只包含給定stop_id分區。這與MySQL分區修剪相同。

大規模並行處理(MPP)
對於第二個查詢,碎片-查詢將掃描分區並聯,基於Gearman的(消息隊列),其在運行工人的數量。如果你有一臺16核心機器,你可以在分區上獲得16度的並行度,而不是MySQL對所有分區的單線程掃描。

只要您的服務器具有處理並行性的資源,您將會看到平行掃描帶來的巨大速度增加。如果沒有,您可以將數據拆分爲N個服務器(這是MPP中的大量數據),您可以在添加節點時獲得線性縮放比例。請記住,如果使用HASH分區,添加或刪除碎片需要重新加載所有數據,所以這應該很少。

警告:
碎片查詢支持COUNT(DISTINCT),但不是SELECT DISTINCT ...
你可以簡單地重寫查詢使用GROUP BY:

查詢#1

select trip_id, stop_sequence from Stop_Times where agency_id = ? and stop_id = ? group by trip_id, stop_sequence; 

查詢#2

select stop_id from Stop_Times where agency_id = ? and trip_id = ? and stop_sequence > ? group by stop_id; 
+0

感謝greenlion。有'分組'的不同方式。我將嘗試這一點。 – Deepu 2012-08-03 07:29:24