使用范围和多个连接优化MySQL查询

时间:2017-06-11 17:25:25

标签: mysql indexing query-optimization sql-optimization amazon-rds-aurora

我希望在下面优化MySQL查询。是否有一个更成功的多列索引?我试过(created_daterep_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

3 个答案:

答案 0 :(得分:0)

添加索引提示:from customer use index (created_date) inner join ...

(请注意,use index并没有按照说明进行操作;它只会让优化程序忽略您不提及的任何索引。)

除此之外,将约会customer_id索引设为(customer_id,current)可能会有所帮助。

答案 1 :(得分:0)

您可能需要一个复合索引 - 类似于:

在客户上创建索引多(id,rep_id,created_date);

MySQL只为每个表使用一个索引(取决于版本,引擎等),如果它认为现有的索引不会有用,它可能会忽略它们。

我假设customer.saved和customer.deleted都是具有很少可能值的列 - 是/否,0/1等。它们往往被查询优化引擎忽略。

答案 2 :(得分:0)

略微重写查询的可读性和与联接中其他表的可视关联..

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)