没有where子句,MySql查询运行速度非常慢(实际上从不提供输出)

时间:2013-09-25 04:41:03

标签: mysql

我有一个mysql查询,当我使用 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  

enter image description here

3 个答案:

答案 0 :(得分:0)

是的,正如许多人所说,关键是当你有where子句时,mysql引擎过滤表M_CLIENT_INFO - 可能是戏剧性的 - 。

删除where子句的结果类似于添加where where子句:

where 1 = 1

你会发现性能下降也是因为mysql会尝试获取所有数据。

答案 1 :(得分:0)

从select中删除where子句和所有列,并添加一个计数以查看您获得的记录数。如果合理,比如高达10k,那么请执行以下操作,

  1. 放回与M_CLIENT_INFO

  2. 相关的选择列
  3. 不包括嵌套的“TAGS”

  4. 删除所有联接

  5. 运行没有where子句的查询,并逐步包含联接

  6. 通过这种方式,您可以了解何时发生超时。

答案 2 :(得分:0)

我会尝试以下方法。首先,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表的实际列,使其与索引匹配

(Date_Added,Client_ID,Name

我在刻度线中有“name”,因为它也是一个保留字,有助于澄清列,而不是关键字。

接下来是WHERE子句。每当您将函数应用于索引列名称时,它都不起作用,尤其是日期/时间字段...您可能希望将where子句更改为

在'2012-01-01'和'2012-12-31 23:59:59'之间添加MCI.Date_

所以BETWEEN范围显示全年,并且可以更好地利用指数。

最后,如果以上内容没有帮助,我会考虑将您的查询拆分一些。 TAGS的GROUP_CONCACT内联选择对您来说可能是一个杀手。您可能希望首先为每个客户端分组所有不同的元素,然后获取这些详细信息....类似

select
      PQ.*,
      group_concat(...) tags
   from
      ( the entire primary part of the query ) as PQ
         Left join yourGroupConcatTableBasis on key columns