[英]MySql query runs very slow(actually never gives output) without where clause
我有一個mysql查詢,當我使用where子句時它運行良好,但是當我不使用where子句時,它消失了,並且從不給出輸出,最后也沒有超時。 實際上,我已經使用Explain命令檢查查詢的性能,並且在兩種情況下, Explain給出的連接使用的行數均相同。 我已經附上了Explain命令獲得的輸出圖像。 下面是查詢。 我不知道這里出了什么問題。 非常感謝您的幫助。 謝謝。
SELECT
MCI.CLIENT_ID AS CLIENT_ID, MCI.NAME AS CLIENT_NAME, MCI.PRIMARY_CONTACT AS CLIENT_PRIMARY_CONTACT,
MCI.ADDED_BY AS SP_ID, CONCAT(MUD_SP.FIRST_NAME, ' ', MUD_SP.LAST_NAME) AS SP_NAME,
MCI.FK_PROSPECT_ID AS PROSPECT_ID, MCI.DATE_ADDED AS ADDED_ON,
(SELECT GROUP_CONCAT(LT.TAG_TEXT SEPARATOR ', ')
FROM LK_TAG LT
INNER JOIN M_OBJECT_TAG_MAPPING MOTM
ON LT.PK_ID = MOTM.FK_TAG_ID
WHERE MOTM.FK_OBJECT_ID = MCI.FK_PROSPECT_ID
AND MOTM.OBJECT_TYPE = 1
AND MOTM.IS_ACTIVE = 1
) AS TAGS,
IFNULL(SUM(GET_DIGITS(MMR.RCP_AMOUNT)), 0) AS REVENUE_SO_FAR,
IFNULL(SUM(GET_DIGITS(MMR.RCP_RUPEES)), 0) AS REVENUE_INR,
COUNT(DISTINCT PMI_MONTHLY.PROJECT_ID) AS MONTHLY,
COUNT(DISTINCT PMI_FIXED.PROJECT_ID) AS FIXED,
COUNT(DISTINCT PMI_HOURLY.PROJECT_ID) AS HOURLY,
COUNT(DISTINCT PMI_ANNUAL.PROJECT_ID) AS ANNUAL,
COUNT(DISTINCT PMI_CURRENTLY_RUNNING.PROJECT_ID) AS CURRENTLY_RUNNING_PROJECTS,
COUNT(DISTINCT PMI_YET_TO_START.PROJECT_ID) AS YET_TO_START_PROJECTS,
COUNT(DISTINCT PMI_TECH_SALES_CLOSED.PROJECT_ID) AS TECH_SALES_CLOSED_PROJECTS
FROM
M_CLIENT_INFO MCI
INNER JOIN M_USER_DETAILS MUD_SP
ON MCI.ADDED_BY = MUD_SP.PK_ID
LEFT OUTER JOIN M_MONTH_RECEIPT MMR
ON MMR.CLIENT_ID = MCI.CLIENT_ID
LEFT OUTER JOIN M_PROJECT_INFO PMI_FIXED
ON PMI_FIXED.CLIENT_ID = MCI.CLIENT_ID AND PMI_FIXED.PROJECT_TYPE = 1
LEFT OUTER JOIN M_PROJECT_INFO PMI_MONTHLY
ON PMI_MONTHLY.CLIENT_ID = MCI.CLIENT_ID AND PMI_MONTHLY.PROJECT_TYPE = 2
LEFT OUTER JOIN M_PROJECT_INFO PMI_HOURLY
ON PMI_HOURLY.CLIENT_ID = MCI.CLIENT_ID AND PMI_HOURLY.PROJECT_TYPE = 3
LEFT OUTER JOIN M_PROJECT_INFO PMI_ANNUAL
ON PMI_ANNUAL.CLIENT_ID = MCI.CLIENT_ID AND PMI_ANNUAL.PROJECT_TYPE = 4
LEFT OUTER JOIN M_PROJECT_INFO PMI_CURRENTLY_RUNNING
ON PMI_CURRENTLY_RUNNING.CLIENT_ID = MCI.CLIENT_ID AND PMI_CURRENTLY_RUNNING.STATUS = 4
LEFT OUTER JOIN M_PROJECT_INFO PMI_YET_TO_START
ON PMI_YET_TO_START.CLIENT_ID = MCI.CLIENT_ID AND PMI_YET_TO_START.STATUS < 4
LEFT OUTER JOIN M_PROJECT_INFO PMI_TECH_SALES_CLOSED
ON PMI_TECH_SALES_CLOSED.CLIENT_ID = MCI.CLIENT_ID AND PMI_TECH_SALES_CLOSED.STATUS > 4
WHERE YEAR(MCI.DATE_ADDED) = '2012'
GROUP BY MCI.CLIENT_ID ORDER BY CLIENT_NAME ASC
是的,正如許多人所說的,關鍵是當您擁有where子句時,mysql引擎會過濾表M_CLIENT_INFO -可能是動態地-。
與刪除where子句類似的結果是添加以下where子句:
where 1 = 1
您還會看到性能下降,因為mysql會嘗試獲取所有數據。
從select中刪除where子句和所有列,並添加計數以查看獲得的記錄數。 如果合理,最多說10k,然后執行以下操作,
放回與M_CLIENT_INFO相關的選擇列
不包括嵌套的一個“ TAGS”
刪除所有聯接
在不使用where子句的情況下運行查詢,並逐漸包含聯接
這樣,您就可以找出造成超時的時間。
我會嘗試以下。 首先,MySQL有一個關鍵字“ STRAIGHT_JOIN”,它告訴優化器按照您指定的表順序進行查詢。 由於所有左聯接都是與子相關的(例如查找表),因此您不希望MySQL嘗試將其中之一解釋為查詢的主要基礎。
SELECT STRAIGHT_JOIN ...其余查詢。
接下來,您的M_PROJECT_INFO表不知道有多少數據列,但是您似乎只專注於DISTINCT聚合中的幾列。 我將確保您在這些元素上具有覆蓋索引,以通過以下索引來幫助查詢
(Client_ID,Project_Type,Status,Project_ID)
這樣,引擎可以應用條件並從索引中獲取唯一的內容,而不必回到原始數據頁面進行查詢。
第三,您的M_CLIENT_INFO表。 確保在兩個條件上都有一個索引,並按AND和Order By進行分組,並通過別名“ CLIENT_NAME”將訂單更改為SQL表的實際列,以使其與索引匹配
(添加日期,客戶ID, Name
)
我在“滴答”中有一個“名稱”,因為它也是一個保留字,可以幫助澄清該列,而不是關鍵字。
接下來,WHERE子句。 每當將函數應用於索引列名時,它都無法發揮最大的作用,尤其是在日期/時間字段上……您可能需要將where子句更改為
WHERE MCI.Date_在“ 2012-01-01”和“ 2012-12-31 23:59:59”之間添加
因此BETWEEN范圍會顯示整個年份,因此可以更好地利用該指數。
最后,如果上述方法沒有幫助,我會考慮將您的查詢拆分一些。 TAGS的GROUP_CONCACT內聯選擇可能對您來說是個殺手er。 您可能希望首先將所有不同的元素用於每個客戶的分組,然后獲取這些詳細信息。
select
PQ.*,
group_concat(...) tags
from
( the entire primary part of the query ) as PQ
Left join yourGroupConcatTableBasis on key columns
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.