具有连接,分组依据,按计数排序的MySQL优化

时间:2017-06-14 02:11:10

标签: mysql optimization indexing query-optimization sql-optimization

以下查询需要花费4秒才能执行,我似乎无法弄清楚原因。我有一个关于客户的索引(保存,删除,创建,rep_id),这消除了全表扫描,但它没有做太多加速...

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

EXPLAIN输出:

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

2 个答案:

答案 0 :(得分:1)

在你加入它们之前,你是否试过缩小你的桌子?

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

答案 1 :(得分:0)

您可以更好地优化索引的另一个选项。保留原始查询相同,只是格式化给我带来了关键组件,以帮助找出索引......

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        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 )

其中一些索引涵盖的索引可以防止需要返回 原始数据页,因为所有关键元素都是索引的一部分。