2014-02-21 58 views
0

我有一個查詢MySQL查詢優化與內部聯接

$query = "SELECT DISTINCT report_date,weekreportDate FROM contract_sales a 
    INNER JOIN contract b ON a.contract_UUID = b.UUID 
    INNER JOIN geoPoint c ON b.customer_UUID = c.customerUUID 
    WHERE c.com_UUID = '$com' AND a.report_date >= Date('$dateafter') 
    AND c.city_UUID = '$cit' ORDER BY `report_date`"; 

,我需要做的是先幹掉通過日期過濾所有的結果,但你可以看到我得到的一切,然後做我的日期排序在檢查..

我內心加入所有這些 - 有沒有更好的方式來做到這一點?

我對每個日期都有一個報告 - 並且有兩年的數據 - 我想在2014年只有日期,所以你可以看到我有700多個日期對我來說很無用,但我必須經過他們都可以檢查其他字符串UUID以及...我能做些什麼來加速我的(工作 - 雖然執行緩慢)?

解釋信息的要求:

Generation Time: Feb 20, 2014 at 06:48 PM 
Generated by: phpMyAdmin 3.3.10.4/MySQL 5.1.53-log 
SQL query: EXPLAIN SELECT DISTINCT report_date,weekreportDate FROM contract_sales a INNER JOIN contract b ON a.contract_UUID = '1234' INNER JOIN geoPoint c ON b.customer_UUID = '1234' WHERE c.com_UUID = '1234' AND a.report_date >= Date('2014-01-01') AND c.city_UUID = '1234' ORDER BY `report_date`; 
Rows: 3 

id select_type table type possible_keys key key_len ref rows Extra 
1 SIMPLE a ref uuid_conlcs uuid_conlcs 110 const 1 Using where; Using temporary; Using filesort 
1 SIMPLE b ref uuid_cust uuid_cust 110 const 1 Using where; Using index; Distinct 
1 SIMPLE c ref uuid_gargp,uuid_citgp uuid_citgp 110 const 1 Using where; Distinct 

回答

1

首先,你的查詢重寫。我不會建議使用別名只是a,b,c,但是更接近於contract_sales的表「cs」的上下文,合同的「con」以及geoPoint的「gp」......在較大的更復雜的查詢中更加容易。

此外,總是嘗試使用table.column(或alias.column)限定您的查詢,因爲WeekReportDate不清楚,但它似乎與您的合同銷售表相關聯。

至於這個構造的索引,我會有一個索引(report_date,weekreportDate,contract_uuid)。通過這種方式,它可以處理被檢索的列,where子句,order by和合同表的連接,而無需返回到原始數據頁面。

合約表,我會有一個關於(UUID,customer_UUID)的索引,也是合約銷售連接的覆蓋索引,也支持到geoPoint表的連接。

最後,您的geoPoint表格(customerUUID,com_uuid,city_uuid)上的索引也覆蓋了聯接和您的過濾標準。

SELECT DISTINCT 
     cs.report_date, 
     cs.weekreportDate 
    FROM 
     contract_sales cs 
     INNER JOIN contract con 
      ON cs.contract_UUID = con.UUID 
      INNER JOIN geoPoint gp 
       ON con.customer_UUID = gp.customerUUID 
       AND gp.com_UUID = '$com' 
       AND gp.city_UUID = '$cit' 
    WHERE 
     cs.report_date >= Date('$dateafter') 
    ORDER BY 
     cs.report_date 

現在這樣說,我不知道你的表音量的妝,但如果你正在尋找的東西特定COM /城市,我會懷疑記錄排位賽,這將是一個問題日期範圍內比所有COM /城市要小得多。所以,我會按照以下方式反轉查詢,希望較小的數據集可能會更快地查詢,但是您必須明確地嘗試兩種方法。

SELECT DISTINCT 
     cs.report_date, 
     cs.weekreportDate 
    FROM 
     geoPoint gp 
     INNER JOIN contract con 
      ON gp.customerUUID = con.customer_UUID 
      JOIN contract_sales cs 
       ON con.UUID = cs.contract_UUID 
       AND cs.report_date >= Date('$dateafter') 
    WHERE 
      gp.com_UUID = '$com' 
     AND gp.city_UUID = '$cit' 
    ORDER BY 
     cs.report_date 

其實GeoPoint的指數應該在你的WHERE條件,然後再對客戶UUID的加入到下一個表(com_uuid,city_uuid,customeruuid)。 (contract_UUID,report_date)上的contract_sales索引以及(customer_UUID,UUID)上的合同表索引,以匹配此查詢的連接流。

+0

謝謝您的詳細信息!它需要我花一些時間來消化你所說的內容,但是從最初的閱讀中我認爲我理解並且會給出這個答案!欣賞它! – morty346

+0

@ morty346,抱歉後期編輯,但第二次查詢實際上會有不同的索引,因爲我修改了答案上下文。 – DRapp