使用union左连接和内连接优化查询

时间:2013-06-12 10:17:43

标签: mysql indexing query-optimization union inner-join

我有一个想要优化的查询。两个工会执行separatley运行正常,但是一旦我包括内连接,它需要长达57秒。我该如何解决这个问题。我的查询如下

SELECT
    p.PROJID,
    p.StartDate,
    o.ORDERNO,
    p.PROJCODE,
    p.PROJECT,
    cat.type AS CATEGORY,
    p.AREA,
    p.STATE,
    p.COUNTRY,
    p.VALUE,
    p.PROCESSOR,
    p.PROJINFO,
    p.NES,
    p.SPECSALE,
    p.OFFICE,
    p.DEPTCODE,
    p.INTERNLCHG,
    p.INTERCOCHG,
    p.LORM,
    p.PERCENT,
    d.COMPANY,
    CONCAT(
        d.LASTNAME,
        ", ",
        d.FIRSTNAME
    ) AS Contact
FROM
    (
        (
            SELECT
                *
            FROM
                (
                    SELECT
                        `clients`.`CLIENTID` AS `CLIENTIDA`,
                        `clients`.`COMPANY` AS `COMPANY`
                    FROM
                        `hdb`.`clients`
                    UNION
                        SELECT
                            `accounts`.`id` AS `CLIENTIDA`,
                            `accounts`.`name` AS `COMPANY`
                        FROM
                            `sugarcrm`.`accounts`
                ) AS a
            INNER JOIN (
                SELECT
                    `hdb`.`contacts`.`CONTACTID` AS `CONTACTID`,
                    `hdb`.`contacts`.`CLIENTID` AS `CLIENTIDC`,
                    `hdb`.`contacts`.`FIRSTNAME` AS `FIRSTNAME`,
                    `hdb`.`contacts`.`LASTNAME` AS `LASTNAME`
                FROM
                    `hdb`.`contacts`
                UNION
                    SELECT
                        `sugarcrm`.`contacts`.`id` AS `CONTACTID`,
                        `sugarcrm`.`accounts_contacts`.`account_id` AS `CLIENTIDC`,
                        `sugarcrm`.`contacts`.`first_name` AS `FIRSTNAME`,
                        `sugarcrm`.`contacts`.`last_name` AS `LASTNAME`
                    FROM
                        `sugarcrm`.`contacts`
                    LEFT JOIN `sugarcrm`.`accounts_contacts` ON `sugarcrm`.`contacts`.`id` = `sugarcrm`.`accounts_contacts`.`contact_id`
            ) AS c ON a.CLIENTIDA = c.CLIENTIDC
        ) AS d
    )
INNER JOIN (
    (
        projects AS p
        INNER JOIN orders AS o ON p.ORDERNO = o.ORDERNO
    )
    INNER JOIN category AS cat ON p.category_id = cat.category_id
) ON d.CONTACTID = o.CONTACTID

对此的解释提供以下内容:

1, PRIMARY, cat, ALL, PRIMARY, , , , 10, 
1, PRIMARY, p, ref, FK_orders_projects,FK_category_projects_idx, FK_category_projects_idx, 5, hdb.cat.category_id, 400, Using where
1, PRIMARY, o, eq_ref, PRIMARY, PRIMARY, 4, hdb.p.ORDERNO, 1, 
1, PRIMARY, <derived2>, ALL, , , , , 18878, Using where
2, DERIVED, <derived3>, ALL, , , , , 7087, 
2, DERIVED, <derived5>, ALL, , , , , 18879, Using where
5, DERIVED, contacts, ALL, , , , , 8261, 
6, UNION, contacts, ALL, , , , , 10251, 
6, UNION, accounts_contacts, ref, idx_contid_del_accid, idx_contid_del_accid, 111, sugarcrm.contacts.id, 1, Using index
, UNION RESULT, <union5,6>, ALL, , , , , , 
3, DERIVED, clients, ALL, , , , , 2296, 
4, UNION, accounts, ALL, , , , , 4548, 
, UNION RESULT, <union3,4>, ALL, , , , , , 

没有联合的原始查询需要0.125秒

SELECT p.PROJID, p.StartDate, o.ORDERNO, p.PROJCODE, p.PROJECT, cat.type AS CATEGORY, p.AREA, p.STATE, p.COUNTRY,
p.VALUE, p.PROCESSOR, p.PROJINFO, p.NES, p.SPECSALE, p.OFFICE, p.DEPTCODE, p.INTERNLCHG, p.INTERCOCHG, p.LORM,
p.PERCENT, a.COMPANY, CONCAT(c.LASTNAME, ", ", c.FIRSTNAME) AS Contact
FROM (clients AS a 
INNER JOIN contacts AS c ON a.CLIENTID =c.CLIENTID) 
INNER JOIN ((projects AS p INNER JOIN orders AS o ON p.ORDERNO = o.ORDERNO) 
INNER JOIN category AS cat ON p.category_id = cat.category_id) ON c.CONTACTID = o.CONTACTID
ORDER BY p.PROJID, a.COMPANY;

解释这提供以下内容:

1, SIMPLE, cat, ALL, PRIMARY, , , , 10, Using temporary; Using filesort
1, SIMPLE, p, ref, FK_orders_projects,FK_category_projects_idx, FK_category_projects_idx, 5, hdb.cat.category_id, 400, Using where
1, SIMPLE, o, eq_ref, PRIMARY,FK_contacts_orders, PRIMARY, 4, hdb.p.ORDERNO, 1, 
1, SIMPLE, c, eq_ref, PRIMARY,FK_clients_contacts, PRIMARY, 52, hdb.o.CONTACTID, 1, 
1, SIMPLE, a, eq_ref, PRIMARY, PRIMARY, 52, hdb.c.CLIENTID, 1, 

查看视图:

SELECT
    p.PROJID,
    p.StartDate,
    o.ORDERNO,
    p.PROJCODE,
    p.PROJECT,
    cat.type AS CATEGORY,
    p.AREA,
    p.STATE,
    p.COUNTRY,
    p.VALUE,
    p.PROCESSOR,
    p.PROJINFO,
    p.NES,
    p.SPECSALE,
    p.OFFICE,
    p.DEPTCODE,
    p.INTERNLCHG,
    p.INTERCOCHG,
    p.LORM,
    p.PERCENT,
    a.COMPANY,
    CONCAT(
        c.LASTNAME,
        ", ",
        c.FIRSTNAME
    ) AS Contact
FROM
    (
        view_accounts_sugar_hdb AS a
        INNER JOIN view_contacts_sugar_hdb AS c ON a.CLIENTID = c.CLIENTID
    )
INNER JOIN (
    (
        projects AS p
        INNER JOIN orders AS o ON p.ORDERNO = o.ORDERNO
    )
    INNER JOIN category AS cat ON p.category_id = cat.category_id
) ON c.CONTACTID = o.CONTACTID
ORDER BY
    p.PROJID,
    a.COMPANY;

这需要340秒。

1 个答案:

答案 0 :(得分:1)

这个绝对比我帮助你的最后一个更丑:)......无论如何,同样的原则也适用。为了将来,请尝试了解我在这里做的事情。首先编写JOIN关系以了解数据的来源。另外,看看我的缩进...我在每个级别都显示可读性。

Orders -> Projects -> Categories...

然后,通过

在普通客户表中的路径
Orders -> Contacts -> Clients
终于到了SugarCRM联系人......

Orders -> Accounts_Contacts -> Accounts

所以,既然你已经设置了关系(和别名),那么就像对正常联系人/客户端与CRM联系人/账户实施LEFT-JOIN的最后一个答案类似。

字段列表在Order,Products和Category表上很简单,因为它们非常直接。只留下LEFT-JOIN所在的“who / client”信息。如果Normal客户端为null,请使用CRM版本字段,否则使用普通客户端字段......

SELECT
      P.PROJID,
      P.StartDate,
      O.ORDERNO,
      P.PROJCODE,
      P.PROJECT,
      cat.`type` AS CATEGORY,
      P.AREA,
      P.STATE,
      P.COUNTRY,
      P.VALUE,
      P.PROCESSOR,
      P.PROJINFO,
      P.NES,
      P.SPECSALE,
      P.OFFICE,
      P.DEPTCODE,
      P.INTERNLCHG,
      P.INTERCOCHG,
      P.LORM,
      P.PERCENT,
      CASE when HCLIENT.ClientID IS NULL
           then SCLIENT.`name`
           ELSE HCLIENT.Company end as Company,
      CASE when HCLIENT.ClientID IS NULL
           then CONCAT( SCT.LAST_NAME, ", ", SCT.FIRST_NAME ) 
           ELSE CONCAT( HCT.LASTNAME, ", ", HCT.FIRSTNAME ) end as Contact
   FROM
      orders O
         JOIN projects P
            ON O.OrderNo = P.OrderNo
            JOIN category AS cat 
               ON p.category_id = cat.category_id

         LEFT JOIN hdb.contacts HCT
            ON O.ContactID = HCT.ContactID
            LEFT JOIN hdb.clients HCLIENT
               ON HCT.ClientID = HCLIENT.ClientID

         LEFT JOIN sugarcrm.contacts SCT
            ON O.ContactID = SCT.ID
            LEFT JOIN sugarcrm.accounts_contacts SAC
               ON SCT.ID = SAC.contact_id
               LEFT JOIN sugarcrm.accounts SCLIENT
                  ON SCT.account_id = SCLIENT.ID

我也对性能改进感兴趣。