2015-07-01 17 views
0

我有一個超過5百萬行的MySQL表(每天都在增長),我試圖根據最常見的查詢來決定在此表上創建哪些索引。這裏是我的表摘要:我的MySQL表中有多個列索引的變化

CREATE TABLE entity (
    entityId CHAR(36) PRIMARY KEY, 
    userId CHAR(36) NOT NULL, 
    status TINYINT NOT NULL, 
    acked BIT NOT NULL, 
    createdAt BIGINT NOT NULL) 

事實上,表中有一些列,但我只寫這些查詢時使用的。這是最常被調用的查詢列表。

查詢1:

SELECT * FROM entity WHERE userId = 'x' AND status = y ORDER BY createdAt DESC LIMIT z 

問題2:

SELECT COUNT(*) FROM entity WHERE userId = 'x' AND status = y 

問題3:

SELECT * FROM entity WHERE userId = 'x' AND status = y AND acked = w ORDER BY createdAt DESC LIMIT z 

問題4:

SELECT COUNT(*) FROM entity WHERE userId = 'x' AND status = y AND acked = w 

查詢5:

SELECT * FROM entity WHERE userId = 'x' ORDER BY createdAt DESC LIMIT z 

查詢6:

SELECT * FROM entity WHERE userId = 'x' AND createdAt < y ORDER BY createdAt DESC LIMIT z 

下面是索引的替代:

索引1:(用戶ID ASC,狀態ASC,ACKED ASC)

索引2:(用戶ID ASC,createdAt ASC,狀態ASC,ACKED ASC)

INDEX3:(用戶ID ASC,createdAt ASC)

Index4:(用戶ID ASC)

我運行EXPLAIN上構建指數組合後的查詢MySQL工作臺的命令。這裏是我的問題:

1.我只使用Index5進行測試並執行查詢5.工作臺在使用Index3時說「成本提示:中 - 部分索引掃描」。並且僅在「使用的關鍵部件」上顯示userId。但是,當我放棄index3並添加index4時,query5顯着減慢。因此,雖然很明顯,部分訂單從其指數中受益,但由於解釋工作臺的報告,我感到困惑。 ORDER BY語句是否直接使用索引?

2.如果對問題1的回答是'是',我認爲一起使用Index1和Index2以使上述所有6個查詢都可以使用。你能提供任何建議嗎?

回答

0

我推薦3個指標SELECTs

SELECT * FROM entity 
     WHERE userId = 'x' AND status = y ORDER BY createdAt DESC LIMIT z 
SELECT COUNT(*) FROM entity 
     WHERE userId = 'x' AND status = y 
-->  INDEX(userId, status, createdAt) -- or 
     INDEX(status, userId, createdAt) 

SELECT * FROM entity 
      WHERE userId = 'x' AND status = y AND acked = w 
      ORDER BY createdAt DESC LIMIT z 
SELECT COUNT(*) FROM entity 
      WHERE userId = 'x' AND status = y AND acked = w 
-->   INDEX(status, userId, acked, createdAt) 
-- This index won't work well on the first queries because `acked` is in the way. 
-- My first index won't work well on these selects because it needs acked. 
-- Again, keep createdAt last; shuffle the others in any way. 

SELECT * FROM entity 
     WHERE userId = 'x' ORDER BY createdAt DESC LIMIT z 
SELECT * FROM entity 
     WHERE userId = 'x' AND createdAt < y ORDER BY createdAt DESC LIMIT z 
-->  INDEX(userId, createdAt) 

您的索引3是多餘的,因爲它是由索引2處理的。但是Index2並不是非常有用,因爲ORDER BY部分不是,而是。也就是說,createdAt之後的字段將不會被使用。

大部分內容在我的cookbook blog中。它說

  1. 處理所有的「=」的WHERE
  2. 區,然後你會得到一個更裂縫 - 在ORDER BYcreatedAt < y
+0

我的3個索引中的任何一個都會「幫助」所有的SELECTs(至少因爲'userId'),但不是最優的。 –

+0

'ASC'是MySQL在索引中做的唯一事情,所以它是'噪聲'。 –