2016-06-10 163 views
0

我正在使用MySQL數據庫。請求您請建議查詢建立的一些良好做法。我已經爲Join on子句列應用了索引。優化包含多於20個內聯表的mysql查詢

下面的查詢需要13秒執行。是否有任何改變方法可以將執行時間縮短到2或3秒?

謝謝。

SELECT * 
    FROM 
     (SELECT pd.id AS pid,pd.request_number,pd.requester, pd.desc_of_auto, 
       pd.benefits,pd.frequency_task, pd.freq_days,pd.time_spent_cur_hr, 
       pd.time_mgr_hr, pd.time_belowmgr_hr,pd.remarks,pd.expected_save_dollar_yr, 
       pd.expected_save_dollar_desc, ROUND(pd.total_time_save_hr) AS total_time_save_hr, 
       pd.total_cost_save, DATE_FORMAT(pd.exp_start_date, '%d-%b-%Y') AS exp_start_date, 
       pd.reasons_challenges_to_start,pd.approx_effort_hr,pd.approx_cost_dollar, 
       DATE_FORMAT(pd.req_date, '%d-%b-%Y') AS req_date, pd.gtmt_hr, 
       DATE_FORMAT(pd.expected_end_date, '%d-%b-%Y') AS expected_end_date, 
       pd.time_mgr_hr_mst,pd.time_belowmgr_hr_mst,pd.gtmt_hr_mst, 
       pd.conversation_rate,pd.higherValues, 
       (SELECT GROUP_CONCAT(DISTINCT dm.dept_name) 
        FROM dept_mst dm 
        LEFT JOIN dept_payback_mst dpm ON dpm.DeptId = dm.id 
         AND dpm.Status = 'Active' 
        WHERE pid = dpm.PaybackId 
      ) AS dept, 
       (SELECT GROUP_CONCAT(DISTINCT dm.id) 
        FROM dept_mst dm 
        LEFT JOIN dept_payback_mst dpm ON dpm.DeptId = dm.id 
         AND dpm.Status = 'Active' 
        WHERE pid = dpm.PaybackId 
      ) AS deptid, 
       (SELECT GROUP_CONCAT(DISTINCT sm.Sbu_name) 
        FROM sbu_mst sm 
        LEFT JOIN sbu_payback_mst spm ON spm.SbuId = sm.Sbu_id 
         AND spm.Status = 'Active' 
        WHERE pid = spm.PaybackId 
         AND sm.Sbu_id IN (1000) 
      ) AS sbu, 
       (SELECT GROUP_CONCAT(DISTINCT sm.Sbu_id) 
        FROM sbu_mst sm 
        LEFT JOIN sbu_payback_mst spm ON spm.SbuId = sm.Sbu_id 
         AND spm.Status = 'Active' 
        WHERE pid = spm.PaybackId 
         AND sm.Sbu_id IN (1000) 
      ) AS sbuid, 
       (SELECT GROUP_CONCAT(DISTINCT cm.Cmp_name) 
        FROM cmp_mst cm 
        LEFT JOIN comp_payback_mst cpm ON cpm.CompId = cm.cmp_id 
         AND cpm.Status = 'Active' 
        WHERE pid = cpm.PaybackId 
      ) AS comp, 
       (SELECT GROUP_CONCAT(DISTINCT cm.cmp_id) 
        FROM cmp_mst cm 
        LEFT JOIN comp_payback_mst cpm ON cpm.CompId = cm.cmp_id 
         AND cpm.Status = 'Active' 
        WHERE pid = cpm.PaybackId 
      ) AS compid, 
       (SELECT GROUP_CONCAT(DISTINCT rm.Resource_Name) 
        FROM resource_mst rm 
        LEFT JOIN resource_payback_mapping rpm ON rpm.resourceId = rm.id 
        WHERE pid = rpm.PaybackId 
      ) AS resreq, 
       (SELECT um.UserName 
        FROM user_mst um 
        WHERE um.id = pd.requester 
      ) AS reqName, 
       (SELECT prm.priority 
        FROM priority_master prm 
        WHERE prm.id = pd.req_priority 
      ) AS reqPriority, 
       (SELECT stm.req_status 
        FROM status_master stm 
        WHERE stm.id = pd.req_status 
         AND stm.req_status = '4- Completed' 
      ) AS reqStatus, 
       (SELECT GROUP_CONCAT(DISTINCT um1.UserName) 
        FROM user_mst um1 
        LEFT JOIN proj_champ_paymst pcp ON pcp.champ_id = um1.id 
         AND pcp.status = 'Active' 
        WHERE pid = pcp.PaybackId 
      ) AS proj_champ, 
       (SELECT GROUP_CONCAT(DISTINCT um2.UserName) 
        FROM user_mst um2 
        LEFT JOIN proj_team_member_paymst ptm ON ptm.team_member_id = um2.id 
         AND ptm.status = 'Active' 
        WHERE pid = ptm.PaybackId 
      ) AS proj_team, 
       (SELECT tym.type 
        FROM type_master tym 
        WHERE tym.id = pd.dataUpload 
      ) AS type, 
       (SELECT fmm.freqName 
        FROM freq_mst fmm 
        WHERE fmm.id = pd.frequency_task 
      ) AS frqName 
      FROM project_detail pd 
      WHERE (pd.total_time_save_hr > 0 
         OR pd.expected_save_dollar_yr > 0 
        ) 
       AND IFNULL(YEAR(expected_end_date), YEAR(NOW())) IN (2015 , 
         2016 
         ) 
      GROUP BY pd.request_number , pd.id 
      ORDER BY DATE(expected_end_date) 
    ) u 
    WHERE reqStatus = '4- Completed' 
     AND sbuid IN (1000) 
     AND compid IN (1000 , 1003,1100,1101,1200,1600, 2001, 2002, 
       2003,2004,2005,2006,4000,4100,4200,4300 
        ) 
+1

關於查詢優化的問題總是需要,作爲最低,爲每一個相關的表的表的語句,還有解釋說查詢。在這種情況下,我很想嘗試減少查詢,只是削弱性能的部分 – Strawberry

+0

謝謝草莓!轉到我的第二個問題,有沒有什麼辦法可以減少上述查詢的執行時間? –

+1

查看之前的評論 – Strawberry

回答

0

您應該重新配置查詢。

sbu_mst JOIN sbu_payback_mst WHERE ...出現兩次。如果不是這樣的子查詢,而是使用JOIN,則不需要評估兩次。

同上cmp_mst

沒有更多的重新安排(和JOINing),你可能會擺脫外部查詢。

WHERE處理這種情況時,請勿使用LEFT。例如:LEFT JOIN sbu_payback_mst spm ... pid = spm.PaybackId

,可能需要一些指標:

dept_payback_mst: (PaybackId, Status, DeptId) 
     -- unless it already has PRIMARY KEY(PaybackId) 
proj_team_member_paymst: (PaybackId) 
+0

完美!我已經用您的建議替換了當前的索引,並且完美地工作。並且還保留了內部查詢中的所有內容。 –