2017-06-05 26 views
2

尋找在MySQL中優化以下查詢的方法。我曾嘗試在sales_date,serviceID和initalStatus上創建多列索引,但未使用。我試圖研究,但是對於優化來說很新,似乎找不到合適的答案。下面是查詢:使用多列索引進行優化MYSQL

SELECT 
COUNT(id) as TotalAccounts, 
AVG(sale_value) AS SaleValue, 
AVG(credit_card = 1) * 100 AS CreditCard, 
SUM(CASE WHEN pre_status = 1 AND bill_status = 'current' THEN 1 
ELSE 0 
END) AS Active, 
SUM(CASE WHEN pre_status = 1 AND bill_status = 'past' THEN 1 
ELSE 0 
END) AS PastDue, 
SUM(CASE WHEN `status` = 0 AND bill_status = 'past' THEN 1 
ELSE 0 
END) AS Canceled 
FROM table_x 
WHERE sales_date >= CAST('2015-01-01' AS DATE) 
AND sales_date <= CAST('2016-01-01' AS DATE) 
AND serviceID = 1 
AND initialStatus = 1 

並解釋輸出:

id:   '1', 
select_type: 'SIMPLE', 
table:   'table_x', 
type:   'ALL', 
possible_keys: 'sales_date,Combo sales_date office_id,salesDate_serviceID_initalStatus', 
key:   NULL, 
key_len:  NULL, 
ref:   NULL, 
rows:   '177585', 
Extra:   'Using where' 

爲背景,共記錄:204830。記錄在我的日期範圍內:65,491。

+0

您是否可以包含用於創建多列索引的代碼? –

+0

可能的錯誤:'sales_date <= CAST('2016-01-01'AS DATE)'包括結束日期。改爲只需'sales_date <'2016-01-01''。還要注意的是鑄造沒有必要。 –

+0

65,491在日期範圍內,但在結果集中有多少? –

回答

1

你應該以不同的順序做對列的索引更好:

ALTER TABLE table_x ADD INDEX (serviceID, initialStatus, sales_date); 

列的索引的順序很重要。您在sales_date上的條件是範圍條件,即它可以匹配多個值。而serviceID和initialStatus上的其他兩個條件是相等條件匹配一個值(或者如果未找到該值,則爲零)。

通常情況下,在索引查找中,所有相等條件必須位於多列索引中最左邊的列上。一旦索引列被用於範圍條件,索引中右側的任何其他列都不會被使用。

假設列(A,B,C)上的索引。

WHERE A=1 AND B=2 AND C=3這樣的條件將使用索引的所有三列。

WHERE A=1 AND B>2 AND C=3這樣的條件將僅使用索引中的列A和B.然後,列C的條件將逐行應用於與A和B條件匹配的所有行。

WHERE A>1 AND B=2 AND C=3這樣的條件將只使用A上的第一列進行索引查找。

您的WHERE子句中的術語順序不需要與索引定義中的列順序相同。 MySQL知道如何重新排列條件以匹配列順序。

您可能會喜歡我的演示文稿How to Design Indexes, Really

+1

謝謝!該指數工作。大幻燈片,他們會幫助我很多。 –

+0

@Bri,以下是視頻:https://www.youtube.com/watch?v = ELR7-RdU9XU –