添加一个子查询会使查询变慢一点,添加另一个使查询变慢

时间:2011-01-05 19:49:39

标签: mysql sql

这很快:

select ba.name,
penamt.value penamt,
#address_line4.value address_line4
from account a
join customer c on a.customer_id = c.id
join branch br on a.branch_id = br.id
join bank ba on br.bank_id = ba.id
join account_address aa on aa.account_id = a.id
join address ad on aa.address_id = ad.id
join state s on ad.state_id = s.id
join import i on a.import_id = i.id
join import_bundle ib on i.import_bundle_id = ib.id
join (select * from unused where heading_label = 'PENAMT') penamt ON penamt.account_id = a.id
#join (select * from unused where heading_label = 'Address Line 4') address_line4 ON address_line4.account_id = a.id
where i.active=1

这很快:

select ba.name,
#penamt.value penamt,
address_line4.value address_line4
from account a
join customer c on a.customer_id = c.id
join branch br on a.branch_id = br.id
join bank ba on br.bank_id = ba.id
join account_address aa on aa.account_id = a.id
join address ad on aa.address_id = ad.id
join state s on ad.state_id = s.id
join import i on a.import_id = i.id
join import_bundle ib on i.import_bundle_id = ib.id
#join (select * from unused where heading_label = 'PENAMT') penamt ON penamt.account_id = a.id
join (select * from unused where heading_label = 'Address Line 4') address_line4 ON address_line4.account_id = a.id
where i.active=1

但这很慢:

select ba.name,
penamt.value penamt,
address_line4.value address_line4
from account a
join customer c on a.customer_id = c.id
join branch br on a.branch_id = br.id
join bank ba on br.bank_id = ba.id
join account_address aa on aa.account_id = a.id
join address ad on aa.address_id = ad.id
join state s on ad.state_id = s.id
join import i on a.import_id = i.id
join import_bundle ib on i.import_bundle_id = ib.id
join (select * from unused where heading_label = 'PENAMT') penamt ON penamt.account_id = a.id
join (select * from unused where heading_label = 'Address Line 4') address_line4 ON address_line4.account_id = a.id
where i.active=1

为什么我只包含两个子查询中的一个时速度很快但是当我包含两个子查询时速度很慢?我认为当我包括两者时它应该是两倍慢,但它需要很长时间。关于MySQL。

这是EXPLAIN

id  select_type table   type    possible_keys   key key_len ref rows    Extra
1   PRIMARY <derived2>  ALL NULL    NULL    NULL    NULL    19584   
1   PRIMARY a   eq_ref  PRIMARY,fk_account_branch_id,fk_account_customer_id,fk_account_import_id    PRIMARY 8   penamt.account_id   1   
1   PRIMARY br  eq_ref  PRIMARY,fk_branch_bank_id   PRIMARY 8   mcif.a.branch_id    1   
1   PRIMARY i   eq_ref  PRIMARY,import_bundle_id    PRIMARY 8   mcif.a.import_id    1   "Using where"
1   PRIMARY ba  eq_ref  PRIMARY PRIMARY 8   mcif.br.bank_id 1   
1   PRIMARY c   eq_ref  PRIMARY PRIMARY 8   mcif.a.customer_id  1   "Using index"
1   PRIMARY ib  eq_ref  PRIMARY PRIMARY 8   mcif.i.import_bundle_id 1   "Using index"
1   PRIMARY aa  ref fk_account_address_account_id,fk_account_address_address_id fk_account_address_account_id   8   mcif.a.id   1   "Using where"
1   PRIMARY <derived3>  ALL NULL    NULL    NULL    NULL    368367  "Using where; Using join buffer"
1   PRIMARY ad  eq_ref  PRIMARY,fk_account_state_id PRIMARY 8   mcif.aa.address_id  1   
1   PRIMARY s   eq_ref  PRIMARY PRIMARY 8   mcif.ad.state_id    1   "Using index"
3   DERIVED unused  ref heading_label   heading_label   257     469722  "Using where"
2   DERIVED unused  ref heading_label   heading_label   257     15632   "Using where"

2 个答案:

答案 0 :(得分:1)

不回答您的确切问题,但如果您更改此类查询以完全摆脱子查询,我敢打赌它会明显更快:

select ba.name,
penamt.value penamt,
address_line4.value address_line4
from account a
join customer c on a.customer_id = c.id
join branch br on a.branch_id = br.id
join bank ba on br.bank_id = ba.id
join account_address aa on aa.account_id = a.id
join address ad on aa.address_id = ad.id
join state s on ad.state_id = s.id
join import i on a.import_id = i.id
join import_bundle ib on i.import_bundle_id = ib.id
left join unused penamt on penamt.account_id = a.id and penamt.heading_label = 'PENAMT'
left join unused address_line4 on address_line4.account_id = a.id and address_line4.heading_label = 'Address Line 4'
where i.active=1

答案 1 :(得分:0)

看来你正在寻找异常数据......那些缺少一些元素,其中你的最后两个查询是针对“未使用”的表,单独查找“heading_label”字段中的PEMAMT或地址行4。此外,除了custoemr帐户的银行分行之外,您不会获得其他信息。那么为什么要添加这些表,除非你的查询工作后你会得到其他数据......那就是说,我会预先查询你的“特殊”标准,然后加入帐户表。使用顶部的“STRAIGHT_JOIN”子句告诉系统按列出的顺序执行此操作。因此,应首先执行预查询,并仅限定那些需要审阅/缺失数据的帐户。然后,在预先查询期间,如果我按最大值分组...并在该查询中获取PENAMT和ADDRESS_LINE_4,我不需要在以后的连接中再次执行它...一切都在前面。

这是我的查询。

select STRAIGHT_JOIN
      ba.name, 
      PreQuery.penamt, 
      PreQuery.address_line4
   from 
      ( SELECT account_id,
               MAX( CASE WHEN heading_label = 'PENAMT' 
                  THEN heading_label END ) penamt,
               MAX( CASE WHEN heading_label = 'Address Line 4' 
                  THEN heading_label END ) Address_line4
         from 
            unused
         where heading_label = 'PENAMT'
            OR heading_label = 'Address Line 4'
         group by 
            unused.account_id ) PreQuery
      join account a 
         ON PreQuery.account_id = a.id
      join customer c 
         on a.customer_id = c.id 
      join branch br 
         on a.branch_id = br.id 
      join bank ba 
         on br.bank_id = ba.id 
      join account_address aa 
         on a.id = aa.account_id
      join address ad 
         on aa.address_id = ad.id 
      join state s 
         on ad.state_id = s.id 
      join import i 
         on a.import_id = i.id 
      join import_bundle ib 
         on i.import_bundle_id = ib.id 
   where 
      i.active = 1