使用范围和多个连接优化 MySQL 查询
Optimize MySQL query with range and multiple joins
我希望优化下面的 MySQL 查询。有没有更成功的多列索引?我试过 (created_date
, rep_id
) 但没有成功。任何加速此查询的建议都值得赞赏。
SELECT
customer.rep_id AS `ID`,
COUNT(*) AS Count,
rep.first_name,
rep.last_name
FROM customer
INNER JOIN appointment ON customer.id = appointment.customer_id
INNER JOIN rep ON customer.rep_id = rep.user_id
INNER JOIN user ON rep.user_id = user.id
WHERE customer.rep_id != 0
AND customer.saved = 0
AND customer.deleted = 0
AND customer.created_date >= '2017-01-01'
AND customer.created_date < '2017-02-01'
AND appointment.current = 1
AND appointment.realStatus IS NOT NULL
AND ( appointment.realStatus not in('rescheduled','cancelled')
OR (appointment.closed_by_id IS NULL
OR customer.rep_id != appointment.closed_by_id)
)
AND user.knocks = 1
AND user.deleted = 0
GROUP BY customer.rep_id
ORDER BY `Count` DESC
LIMIT 50
这是 EXPLAIN
输出:
id: 1
select_type: SIMPLE
table: customer
type: range
possible_keys: PRIMARY,rep_id,created_date
key: NULL
key_len: NULL
ref: NULL
rows: 354846
Extra: Using where; Using temporary; Using filesort
id: 1
select_type: SIMPLE
table: rep
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: rep.user_id
rows: 1
Extra: Using where
id: 1
select_type: SIMPLE
table: appointment
type: ref
possible_keys: realStatus, customer_id, created_date
key: customer_id
key_len: 4
ref: customer.id
rows: 1
Extra: Using where
添加索引提示:from customer use index (created_date) inner join ...
(请注意 use index
并没有按照它所说的去做;它只是让优化器忽略您没有提及的任何索引。)
除此之外,将约会 customer_id 索引设为 (customer_id,current)
可能会有帮助。
您可能需要一个复合索引 - 例如:
在客户 (id, rep_id, created_date) 上创建索引 multi;
MySQL 只为每个 table 使用一个索引(取决于版本、引擎等),如果它认为现有索引不会有帮助,它可能会忽略他们。
我假设 customer.saved 和 customer.deleted 都是可能值很少的列 - yes/no、0/1 等。查询优化引擎往往会忽略它们。
为了可读性和与连接中其他表的视觉关联,稍微重写了查询..
SELECT
customer.rep_id AS `ID`,
COUNT(*) AS Count,
rep.first_name,
rep.last_name
FROM
customer
INNER JOIN appointment
ON customer.id = appointment.customer_id
AND appointment.current = 1
AND appointment.realStatus IS NOT NULL
INNER JOIN rep
ON customer.rep_id = rep.user_id
INNER JOIN user
ON rep.user_id = user.id
AND user.knocks = 1
AND user.deleted = 0
WHERE
customer.rep_id != 0
AND customer.saved = 0
AND customer.deleted = 0
AND customer.created_date >= '2017-01-01'
AND customer.created_date < '2017-02-01'
AND ( appointment.realStatus not in('rescheduled','cancelled')
OR ( appointment.closed_by_id IS NULL
OR customer.rep_id != appointment.closed_by_id ))
GROUP BY
customer.rep_id
ORDER BY
`Count` DESC
LIMIT
50
您可能需要多个复合索引来帮助查询。此外,我移动了一些查询元素以更好地匹配条件适用的地方(例如约会和用户)。这也有助于确定更好的索引选项。也就是说,我会在每个
上提供以下索引
table index
customer (saved, deleted, created_date, rep_id )
rep (user_id)
appointment (customer_id, current, realStatus)
我希望优化下面的 MySQL 查询。有没有更成功的多列索引?我试过 (created_date
, rep_id
) 但没有成功。任何加速此查询的建议都值得赞赏。
SELECT
customer.rep_id AS `ID`,
COUNT(*) AS Count,
rep.first_name,
rep.last_name
FROM customer
INNER JOIN appointment ON customer.id = appointment.customer_id
INNER JOIN rep ON customer.rep_id = rep.user_id
INNER JOIN user ON rep.user_id = user.id
WHERE customer.rep_id != 0
AND customer.saved = 0
AND customer.deleted = 0
AND customer.created_date >= '2017-01-01'
AND customer.created_date < '2017-02-01'
AND appointment.current = 1
AND appointment.realStatus IS NOT NULL
AND ( appointment.realStatus not in('rescheduled','cancelled')
OR (appointment.closed_by_id IS NULL
OR customer.rep_id != appointment.closed_by_id)
)
AND user.knocks = 1
AND user.deleted = 0
GROUP BY customer.rep_id
ORDER BY `Count` DESC
LIMIT 50
这是 EXPLAIN
输出:
id: 1
select_type: SIMPLE
table: customer
type: range
possible_keys: PRIMARY,rep_id,created_date
key: NULL
key_len: NULL
ref: NULL
rows: 354846
Extra: Using where; Using temporary; Using filesort
id: 1
select_type: SIMPLE
table: rep
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: rep.user_id
rows: 1
Extra: Using where
id: 1
select_type: SIMPLE
table: appointment
type: ref
possible_keys: realStatus, customer_id, created_date
key: customer_id
key_len: 4
ref: customer.id
rows: 1
Extra: Using where
添加索引提示:from customer use index (created_date) inner join ...
(请注意 use index
并没有按照它所说的去做;它只是让优化器忽略您没有提及的任何索引。)
除此之外,将约会 customer_id 索引设为 (customer_id,current)
可能会有帮助。
您可能需要一个复合索引 - 例如:
在客户 (id, rep_id, created_date) 上创建索引 multi;
MySQL 只为每个 table 使用一个索引(取决于版本、引擎等),如果它认为现有索引不会有帮助,它可能会忽略他们。
我假设 customer.saved 和 customer.deleted 都是可能值很少的列 - yes/no、0/1 等。查询优化引擎往往会忽略它们。
为了可读性和与连接中其他表的视觉关联,稍微重写了查询..
SELECT
customer.rep_id AS `ID`,
COUNT(*) AS Count,
rep.first_name,
rep.last_name
FROM
customer
INNER JOIN appointment
ON customer.id = appointment.customer_id
AND appointment.current = 1
AND appointment.realStatus IS NOT NULL
INNER JOIN rep
ON customer.rep_id = rep.user_id
INNER JOIN user
ON rep.user_id = user.id
AND user.knocks = 1
AND user.deleted = 0
WHERE
customer.rep_id != 0
AND customer.saved = 0
AND customer.deleted = 0
AND customer.created_date >= '2017-01-01'
AND customer.created_date < '2017-02-01'
AND ( appointment.realStatus not in('rescheduled','cancelled')
OR ( appointment.closed_by_id IS NULL
OR customer.rep_id != appointment.closed_by_id ))
GROUP BY
customer.rep_id
ORDER BY
`Count` DESC
LIMIT
50
您可能需要多个复合索引来帮助查询。此外,我移动了一些查询元素以更好地匹配条件适用的地方(例如约会和用户)。这也有助于确定更好的索引选项。也就是说,我会在每个
上提供以下索引table index
customer (saved, deleted, created_date, rep_id )
rep (user_id)
appointment (customer_id, current, realStatus)