SQL优化 - 慢查询

时间:2013-04-16 10:11:24

标签: mysql sql optimization

鉴于SQL需要1.2s:

SELECT DISTINCT contracts.id, jt0.id, jt1.id, jt2.id, jt3.id FROM contracts
LEFT JOIN accounts jt0 ON jt0.id = contracts.account_id AND jt0.deleted=0
LEFT JOIN manufacturers jt1 ON jt1.id = contracts.manufacturer_id AND jt1.deleted=0
LEFT JOIN products jt2 ON jt2.id = contracts.product_id AND jt2.deleted=0
LEFT JOIN users jt3 ON jt3.id = contracts.assigned_user_id AND jt3.deleted=0
WHERE contracts.deleted=0
ORDER BY contracts.application_number ASC 
LIMIT 0,21

这是解释扩展回报的原因:

id  select_type table   type    possible_keys   key key_len ref rows
1   SIMPLE  contracts   ref idx_contracts_deleted   idx_contracts_deleted   2   const   18968   100.00  Using where; Using temporary; Using filesort
1   SIMPLE  jt0 eq_ref  PRIMARY,idx_accnt_id_del,idx_accnt_assigned_del PRIMARY 108 xxx.contracts.account_id    1   100.00  
1   SIMPLE  jt1 eq_ref  PRIMARY,idx_manufacturers_id_deleted,idx_manufacturers_deleted  PRIMARY 108 xxx.contracts.manufacturer_id   1   100.00  
1   SIMPLE  jt2 eq_ref  PRIMARY,idx_products_id_deleted,idx_products_deleted    PRIMARY 108 xxx.contracts.product_id    1   100.00  
1   SIMPLE  jt3 eq_ref  PRIMARY,idx_users_id_del,idx_users_id_deleted,idx_users_deleted PRIMARY 108 xxx.contracts.assigned_user_id  1   100.00  

我需要与众不同,我需要留下所有的联接,我需要订购,我需要限制 我能以某种方式对其进行优化吗?

4 个答案:

答案 0 :(得分:0)

这是我唯一的建议

  1. 我希望id被定义为主键和外键与表之间的关系。

  2. 也许可以索引application_number(然后排序会更快)

  3. 也许,如果您使用MyISAM,如果您在选择之前锁定表格(不要忘记之后解锁),则SQL可能会更快

答案 1 :(得分:0)

首先在以下列中创建必要的索引。

contracts.application_number,manufacturers.deleted,products.deleted,users.deleted

SELECT DISTINCT contracts.id, jt0.id, jt1.id, jt2.id, jt3.id 
FROM contracts
LEFT JOIN accounts jt0 
ON contracts.deleted=0 AND jt0.id = contracts.account_id
LEFT JOIN manufacturers jt1 
ON jt1.deleted=0 AND jt1.id = contracts.manufacturer_id
LEFT JOIN products jt2 
ON jt2.deleted=0 AND jt2.id = contracts.product_id
LEFT JOIN users jt3 
ON jt3.deleted=0 AND jt3.id = contracts.assigned_user_id
ORDER BY contracts.application_number ASC 
LIMIT 0,21

正如您所提到的,您已经在contract.deleted

上编制了索引
FROM 
  (SELECT * FROM contracts WHERE contracts.deleted = 0 USE INDEX(<deletedIndexName>))
LEFT JOIN 
  accounts jt0 
ON 
  jt0.id = contracts.account_id
LEFT JOIN  
  ...

答案 2 :(得分:0)

尝试更改子表上的索引以包含deleted列:

  • accounts(id, deleted)
  • manufacturers(id, deleted)
  • products(id, deleted)
  • users(id, deleted)

通过在索引中包含所有列,MySQL可以更好地利用索引。

另一个建议是找出导致值重复的原因,并使用子查询来消除重复,而不是distinct

例如,使用以上索引:

from contracts c left join
     (select id
      from accounts
      where deleted = 0
      group by id
     ) a
     on c.account_id = a.id
     . . .

子查询应该只使用索引,这可能会加快速度。

答案 3 :(得分:0)

尝试一点参考完整性?我敢打赌,内部联接的查询速度要快得多。它应该是,因为查询优化器有更多的工作。您需要在select时付费,因为create没有更多关注。

我还会删除已删除的行到他们自己的表中,并点击deleted列。您的查询将更简单,并且可能运行得更快。