使用mysql中的连接优化查询

时间:2013-06-11 09:40:33

标签: mysql performance query-optimization

我有一个想要优化的查询,需要29秒才能完成。我已经尝试创建了一个联合连接的视图,但结果却更糟。

 select o.orderno, o.orderdate, c.lastname 
from orders o 
join (select 
    `hdb`.`contacts`.`CONTACTID` AS `CONTACTID`, 
    `hdb`.`contacts`.`LASTNAME` AS `LASTNAME`
    from `hdb`.`contacts` 
    union 
select 
    `sugarcrm`.`contacts`.`id` AS `CONTACTID`,
    `sugarcrm`.`contacts`.`last_name` AS `LASTNAME`
    from `sugarcrm`.`contacts` ) c on c.CONTACTID = o.CONTACTID  


order by orderno desc
limit 0,100000000

在mysql慢查询日志下,我得到以下部分:

select 
        `hdb`.`contacts`.`CONTACTID` AS `CONTACTID`, 
        `hdb`.`contacts`.`CLIENTID` AS `CLIENTID`, 
         concat(`hdb`.`contacts`.`FIRSTNAME`,_utf8' ',coalesce(`hdb`.`contacts`.`INITIALS`,_utf8'')) AS `FIRSTNAME`, 
        `hdb`.`contacts`.`LASTNAME` AS `LASTNAME`, 
        `hdb`.`contacts`.`PHONE` AS `PHONE`, 
        `hdb`.`contacts`.`FAX` AS `FAX`, 
        `hdb`.`contacts`.`DEPARTMENT` AS `DEPARTMENT`, 
        `hdb`.`contacts`.`TITLE` AS `TITLE`, 
        `hdb`.`contacts`.`INFO` AS `INFO`, 
        `hdb`.`contacts`.`SALUTATION` AS `SALUTATION`, 
        `hdb`.`contacts`.`EMAIL` AS `EMAIL`,    
        CASE 
            WHEN `hdb`.`contacts`.`ACTIVE` != 0 THEN 0
            ELSE 1
        END DELETED,        
        'paradox' AS `SOURCEDATABASE`
        from `hdb`.`contacts` 
        union 
    select 
        `sugarcrm`.`contacts`.`id` AS `CONTACTID`,
        `sugarcrm`.`accounts_contacts`.`account_id` AS `CLIENTID`,
        `sugarcrm`.`contacts`.`first_name` AS `FIRSTNAME`,
        `sugarcrm`.`contacts`.`last_name` AS `LASTNAME`,
        `sugarcrm`.`contacts`.`phone_work` AS `PHONE`,
        `sugarcrm`.`contacts`.`phone_fax` AS `FAX`,
        `sugarcrm`.`contacts`.`department` AS `department`,
        `sugarcrm`.`contacts`.`title` AS `title`,
        `sugarcrm`.`contacts`.`description` AS `INFO`,
        `sugarcrm`.`contacts`.`salutation` AS `salutation`,
        `sugarcrm`.`email_addresses`.`email_address` AS `Email`,            
        `sugarcrm`.`contacts`.`deleted` AS DELETED,
        'sugar' AS `SOURCEDATABASE` 
        from (((`sugarcrm`.`contacts` 
        left join `sugarcrm`.`email_addr_bean_rel` 
        on((`sugarcrm`.`contacts`.`id` = `sugarcrm`.`email_addr_bean_rel`.`bean_id`))) 
        left join `sugarcrm`.`accounts_contacts` 
        on((`sugarcrm`.`contacts`.`id` = `sugarcrm`.`accounts_contacts`.`contact_id`))) 
        join `sugarcrm`.`email_addresses` 
        on((`sugarcrm`.`email_addr_bean_rel`.`email_address_id` = `sugarcrm`.`email_addresses`.`id`)))

但如果单独运行,这会很快运行。使用说明给我以下内容。

1, PRIMARY, o, ALL, , , , , 6085, Using temporary; Using filesort
1, PRIMARY, <derived2>, ALL, , , , , 18877, Using where
2, DERIVED, contacts, ALL, , , , , 8009, 
3, UNION, contacts, ALL, , , , , 10251, 
, UNION RESULT, <union2,3>, ALL, , , , , , 

1 个答案:

答案 0 :(得分:1)

对于您的热门查询,我会将其更改为双左连接到每个相应的联系人表...也就是说,看起来客户的联系人ID应该是其中的任何一个(除非您有其他联系表) 。也就是说,左连接比执行预查询/连接更快。对于名称,我会case / when ...如果一个表没有匹配(通过IS NULL),则使用另一个表中的名称,反之亦然...如果它有值,用它。然后,只需确保您的订单表上有订单号的索引。

select 
      o.orderno, 
      o.orderdate, 
      CASE when hc.contactid is null 
           then sc.last_name else hc.lastname end as LastName
   from 
      orders o 
         LEFT JOIN hdb.contacts hc
            ON o.ContactID = hc.ContactID
         LEFT JOIN sugarcrm.contacts sc
            ON o.ContactID = sc.id
   order by 
      orderno desc
   limit 0, 100000000

如果您有其他联系人表,但只关心那些与“hc”和“sc”别名表相关联的表,我会为

添加一个WHERE子句
WHERE hc.contactID IS NOT NULL
   OR sc.id IS NOT NULL

确保至少有一个表有匹配。