使用多列索引进行优化 MYSQL
Optimize with Multi Column Index MYSQL
正在寻找优化 MySQL 中以下查询的方法。我已经尝试在 sales_date、serviceID 和 initalStatus 上创建多列索引,但它没有被使用。我曾尝试研究,但对优化不熟悉,似乎找不到合适的答案。下面是查询:
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
以及 EXPLAIN 输出:
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'
对于上下文,总记录:204,830。我的日期范围内的记录:65,491。
您应该使用不同顺序的列索引做得更好:
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。
正在寻找优化 MySQL 中以下查询的方法。我已经尝试在 sales_date、serviceID 和 initalStatus 上创建多列索引,但它没有被使用。我曾尝试研究,但对优化不熟悉,似乎找不到合适的答案。下面是查询:
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
以及 EXPLAIN 输出:
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'
对于上下文,总记录:204,830。我的日期范围内的记录:65,491。
您应该使用不同顺序的列索引做得更好:
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。