0

给定 SQL 需要 1.2 秒:

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

4 回答 4

0

尝试一点参照完整性?我敢打赌,使用内部连接查询会快得多。应该是,因为查询优化器有更多的工作要做。您正在select为不更关心create.

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

于 2013-04-17T07:22:10.950 回答
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
     . . .

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

于 2013-04-16T10:54:01.400 回答
0

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

contract.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

正如您所提到的,您已经在contracts.deleted上建立了索引

FROM 
  (SELECT * FROM contracts WHERE contracts.deleted = 0 USE INDEX(<deletedIndexName>))
LEFT JOIN 
  accounts jt0 
ON 
  jt0.id = contracts.account_id
LEFT JOIN  
  ...
于 2013-04-16T10:30:40.683 回答
0

这些是我得到的唯一建议

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

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

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

于 2013-04-16T10:18:06.737 回答