簡體   English   中英

使用范圍和多個聯接優化MySQL查詢

[英]Optimize MySQL query with range and multiple joins

我正在尋找優化下面的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

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

(請注意, use index並沒有執行它所說的;它只是使優化器忽略了您未提及的任何索引。)

除此之外,將約會customer_id索引設為(customer_id,current)可能會有所幫助。

您可能需要復合索引-類似:

在客戶上創建多個索引(id,rep_id,created_date);

MySQL對每個表只使用一個索引(取決於版本,引擎等),如果它認為現有索引不會有幫助,則可以忽略它們。

我假設customer.saved和customer.deleted都是可能值很少的列-是/否,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)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM