MySQL 通过连接、分组依据、计数排序进行优化
MySQL optimization with joins, group by, order by count
以下查询的执行时间高达 4 秒,我似乎无法弄清楚原因。我有一个关于客户的索引(已保存、已删除、已创建,rep_id),它消除了完整的 table 扫描,但它对加快速度没有太大作用...
SELECT
customer.rep_id AS `ID`,
COUNT(*) AS Count,
rep.name
FROM customer
INNER JOIN appointment ON customer.id = appointment.customer_id
AND appointment.date >= '2017-05-01'
AND appointment.date < '2017-06-01'
AND appointment.current = 1
AND appointment.`status` = 'completed'
INNER JOIN rep ON customer.rep_id = rep.user_id
INNER JOIN user ON rep.user_id = user.id
AND user.active = 1
AND user.deleted = 0
WHERE customer.rep_id != 0
AND customer.saved = 0
AND customer.deleted = 0
GROUP BY customer.rep_id
ORDER BY `Count` DESC
LIMIT 50
解释输出:
id 1
select_type SIMPLE
table customer
type ref
possible_keys PRIMARY,rep_id,saved_deleted_created_rep,rep_saved_deleted_created
key saved_deleted_created_rep
key_len 2
ref const,const
rows 162007
Extra Using where; Using index; Using temporary; Using filesort
id 1
select_type SIMPLE
table contact
type ref
possible_keys user_id
key user_id
key_len 4
ref customer.rep_id
rows 1
Extra Using index condition
id 1
select_type SIMPLE
table user
type eq_ref
possible_keys PRIMARY
key PRIMARY
key_len 4
ref contact.user_id
rows 1
Extra Using where
id 1
select_type SIMPLE
table appointment
type ref
possible_keys status,date,customer_id
key customer_id
key_len 4
ref customer.id
rows 1
Extra Using where
在将它们全部合并之前,您是否尝试缩小 table 范围?
SELECT
customer.rep_id AS `ID`,
COUNT(*) AS Count,
contact.name
FROM
(
SELECT
id, rep_id
FROM
customer
JOIN (
SELECT
customer_id
FROM
appointment
WHERE
date >= '2017-05-01'
AND
appointment.date < '2017-06-01'
AND
appointment.current = 1
AND
appointment.`status` = 'completed'
) AS appointment
ON customer.id = appointment.customer_id
WHERE
customer.rep_id != 0
AND
customer.saved = 0
AND
customer.deleted = 0
) AS customer
JOIN contact
ON customer.rep_id = contact.user_id
JOIN (
SELECT
id
FROM
user
WHERE
user.active = 1
AND
user.deleted = 0
) AS user
ON contact.user_id = user.id
GROUP BY customer.rep_id
ORDER BY `Count` DESC
LIMIT 50
您可以更好地优化索引的另一种选择。让您的原始查询保持不变,只需对我进行格式化即可显示关键组件以帮助找出索引...
SELECT
customer.rep_id AS `ID`,
COUNT(*) AS Count,
rep.name
FROM
customer
INNER JOIN appointment
ON customer.id = appointment.customer_id
AND appointment.date >= '2017-05-01'
AND appointment.date < '2017-06-01'
AND appointment.current = 1
AND appointment.`status` = 'completed'
INNER JOIN rep
ON customer.rep_id = rep.user_id
INNER JOIN user
ON rep.user_id = user.id
AND user.active = 1
AND user.deleted = 0
WHERE
customer.rep_id != 0
AND customer.saved = 0
AND customer.deleted = 0
GROUP BY
customer.rep_id
ORDER BY
`Count` DESC
LIMIT
50
帮助您查询的索引...不仅是客户 table,还有约会、代表和用户 table...
table index
customer ( saved, deleted, rep_id, id, created ) although created does not appear required
appointment ( customer_id, current, `status`, date )
rep ( user_id, name )
user ( id, active, deleted )
其中一些索引覆盖了不需要返回到
原始数据页,因为所有关键元素都是索引的一部分。
以下查询的执行时间高达 4 秒,我似乎无法弄清楚原因。我有一个关于客户的索引(已保存、已删除、已创建,rep_id),它消除了完整的 table 扫描,但它对加快速度没有太大作用...
SELECT
customer.rep_id AS `ID`,
COUNT(*) AS Count,
rep.name
FROM customer
INNER JOIN appointment ON customer.id = appointment.customer_id
AND appointment.date >= '2017-05-01'
AND appointment.date < '2017-06-01'
AND appointment.current = 1
AND appointment.`status` = 'completed'
INNER JOIN rep ON customer.rep_id = rep.user_id
INNER JOIN user ON rep.user_id = user.id
AND user.active = 1
AND user.deleted = 0
WHERE customer.rep_id != 0
AND customer.saved = 0
AND customer.deleted = 0
GROUP BY customer.rep_id
ORDER BY `Count` DESC
LIMIT 50
解释输出:
id 1
select_type SIMPLE
table customer
type ref
possible_keys PRIMARY,rep_id,saved_deleted_created_rep,rep_saved_deleted_created
key saved_deleted_created_rep
key_len 2
ref const,const
rows 162007
Extra Using where; Using index; Using temporary; Using filesort
id 1
select_type SIMPLE
table contact
type ref
possible_keys user_id
key user_id
key_len 4
ref customer.rep_id
rows 1
Extra Using index condition
id 1
select_type SIMPLE
table user
type eq_ref
possible_keys PRIMARY
key PRIMARY
key_len 4
ref contact.user_id
rows 1
Extra Using where
id 1
select_type SIMPLE
table appointment
type ref
possible_keys status,date,customer_id
key customer_id
key_len 4
ref customer.id
rows 1
Extra Using where
在将它们全部合并之前,您是否尝试缩小 table 范围?
SELECT
customer.rep_id AS `ID`,
COUNT(*) AS Count,
contact.name
FROM
(
SELECT
id, rep_id
FROM
customer
JOIN (
SELECT
customer_id
FROM
appointment
WHERE
date >= '2017-05-01'
AND
appointment.date < '2017-06-01'
AND
appointment.current = 1
AND
appointment.`status` = 'completed'
) AS appointment
ON customer.id = appointment.customer_id
WHERE
customer.rep_id != 0
AND
customer.saved = 0
AND
customer.deleted = 0
) AS customer
JOIN contact
ON customer.rep_id = contact.user_id
JOIN (
SELECT
id
FROM
user
WHERE
user.active = 1
AND
user.deleted = 0
) AS user
ON contact.user_id = user.id
GROUP BY customer.rep_id
ORDER BY `Count` DESC
LIMIT 50
您可以更好地优化索引的另一种选择。让您的原始查询保持不变,只需对我进行格式化即可显示关键组件以帮助找出索引...
SELECT
customer.rep_id AS `ID`,
COUNT(*) AS Count,
rep.name
FROM
customer
INNER JOIN appointment
ON customer.id = appointment.customer_id
AND appointment.date >= '2017-05-01'
AND appointment.date < '2017-06-01'
AND appointment.current = 1
AND appointment.`status` = 'completed'
INNER JOIN rep
ON customer.rep_id = rep.user_id
INNER JOIN user
ON rep.user_id = user.id
AND user.active = 1
AND user.deleted = 0
WHERE
customer.rep_id != 0
AND customer.saved = 0
AND customer.deleted = 0
GROUP BY
customer.rep_id
ORDER BY
`Count` DESC
LIMIT
50
帮助您查询的索引...不仅是客户 table,还有约会、代表和用户 table...
table index
customer ( saved, deleted, rep_id, id, created ) although created does not appear required
appointment ( customer_id, current, `status`, date )
rep ( user_id, name )
user ( id, active, deleted )
其中一些索引覆盖了不需要返回到 原始数据页,因为所有关键元素都是索引的一部分。