2012-09-19 117 views
1

我与现有的网站工作,我碰到下面的MySQL查询需要进行优化传来:MySQL查询优化复杂的查询

select 
    mo.mmrrc_order_oid, 
    mo.completed_by_email, 
    mo.completed_by_name, 
    mo.completed_by_title, 
    mo.order_submission_oid, 
    mo.order_dt, 
    mo.center_id, 
    mo.po_num_tx, 
    mo.mod_dt, 
    ste_s.state_cd, 
    group_concat(distinct osr.status_cd order by osr.status_cd) as test, 
    case group_concat(distinct osr.status_cd order by osr.status_cd) 
     when 'Fulfilled' then 'Fulfilled' 
     when 'Fulfilled,N/A' then 'Fulfilled' 
     when 'N/A' then 'N/A' 
     when 'Pending' then 'Pending' 
     else 'In Process' 
    end as restriction_status, 
    max(osr.closed_dt) as restriction_update_dt, 
    ot.milestone, 
    ot.completed_dt as tracking_update_dt, 
    dc.first_name, 
    dc.last_name, 
    inst.institution_name, 
    order_search.products as products_ordered, 
    mo.other_emails, 
    mo.customer_label, 
    mo.grant_numbers 
from 
    t_mmrrc_order mo 
    join ste_state ste_s using(state_id) 
    left join t_order_contact oc 
     on oc.mmrrc_order_oid=mo.mmrrc_order_oid and oc.role_cd='Recipient' 
    left join t_distrib_cont_instn dci using(distrib_cont_instn_oid) 
    left join t_institution inst using(institution_oid) 
    left join t_distribution_contact dc using(distribution_contact_oid) 
    left join t_order_tracking ot 
     on ot.mmrrc_order_oid=mo.mmrrc_order_oid 
      and ifnull(ot.order_tracking_oid, '0000-00-00')= ifnull(
       (
       select max(order_tracking_oid) 
       from t_order_tracking ot3 
       where 
        ot3.mmrrc_order_oid=mo.mmrrc_order_oid 
        and ot3.completed_dt= (
          select max(completed_dt) 
          from t_order_tracking ot2 
          where ot2.mmrrc_order_oid=mo.mmrrc_order_oid 
         ) 
       ), '0000-00-00') 
    left join t_order_strain_restriction osr 
     on osr.mmrrc_order_oid = mo.mmrrc_order_oid 
    left join order_search on order_search.mmrrc_order_oid=mo.mmrrc_order_oid 
group by 
    mo.mmrrc_order_oid 
LIMIT 0, 5 

这个查询需要10+秒无论极限运行。当运行没有限制时,总共有5,727个结果,运行时间是10.624秒。

“限制0,5”花了18.47秒。

我知道有一堆连接和嵌套选择,这就是为什么它如此缓慢。关于如何优化这个而不必改变数据库结构的想法?

MySQL版本:5.0.95

大多数表格都有超过10,000条记录。

这种简单的查询需要约9秒:

select 
    mo.mmrrc_order_oid, 
    mo.completed_by_email, 
    mo.completed_by_name, 
    mo.completed_by_title, 
    mo.order_submission_oid, 
    mo.order_dt, 
    mo.center_id, 
    mo.po_num_tx, 
    mo.mod_dt, 
    dc.first_name, 
    dc.last_name, 
    inst.institution_name, 
    order_search.products as products_ordered, 
    mo.other_emails, 
    mo.customer_label, 
    mo.grant_numbers 
from 
    t_mmrrc_order mo 
    join ste_state ste_s using(state_id) 
    left join t_order_contact oc 
     on oc.mmrrc_order_oid=mo.mmrrc_order_oid and oc.role_cd='Recipient' 
    left join t_distrib_cont_instn dci using(distrib_cont_instn_oid) 
    left join t_institution inst using(institution_oid) 
    left join t_distribution_contact dc using(distribution_contact_oid) 
    left join t_order_strain_restriction osr 
     on osr.mmrrc_order_oid = mo.mmrrc_order_oid 
    left join order_search on order_search.mmrrc_order_oid=mo.mmrrc_order_oid 
group by mo.mmrrc_order_oid 
limit 0,5 

我想分组减缓下来最多。在这种情况下,没有分组只需要0.17秒。任何帮助,将不胜感激。谢谢。

其他详细信息 - 这里是解释什么让我对第一个查询: View Image enter image description here

我发现order_search是导致大多数慢下来的景色。视图的查询:

SELECT 
    t_oi.mmrrc_order_oid AS mmrrc_order_oid, 
    group_concat(t_im.icc_item_code separator ',') AS products 
FROM 
    t_order_item t_oi 
    JOIN t_item_master t_im on t_oi.item_master_oid = t_im.item_master_oid 
    JOIN t_strain_archive on t_im.strain_archive_oid = t_strain_archive.strain_archive_oid 
WHERE t_oi.item_status_cd IN (_utf8'Active',_utf8'Modified') 
GROUP BY t_oi.mmrrc_order_oid 
ORDER BY t_im.icc_item_code 
+3

['EXPLAIN'](http://dev.mysql.com/doc/refman/5.0/en/explain.html)可以告诉你更多关于为什么这个查询比我们'将能够。 –

+0

谢谢,我已经添加了来自EXPLAIN的输出。仍然不知道如何优化。 – coder4life

+0

你有没有添加coloumns索引如果添加所以请张贴 –

回答

0

我设法从我的PHP脚本做两个单独的查询来解决这个问题也coloumns应用此操作。 首先,我自己查询order_search视图,并将所有数据保存在由mmrrc_order_oid索引的PHP数组中,然后用作产品的快速查找表。这个结果查找表是一个约有6000个字符串的数组。

接下来,我用order_search表省略了大型复杂查询。这只需要一秒钟。对于每个结果记录,我只需使用mmrrc_order_oid的查找表来获取该订单的产品。

0

只是假设你没有索引coloumns,所以我为你的coloumns一些指标,这将有助于你仍然有很多coloumns索引就像在你加盟的条件,你应该对为更好的执行

ALTER TABLE `t_mmrrc_order` ADD INDEX `Indexnamemmrrc_order_oid` (`mmrrc_order_oid`); 
ALTER TABLE `t_mmrrc_order` ADD INDEX `Indexnamecompleted_by_email` (`completed_by_email`); 
ALTER TABLE `t_mmrrc_order` ADD INDEX `Indexnamecompleted_by_name` (`completed_by_name`); 
ALTER TABLE `t_mmrrc_order` ADD INDEX `Indexnamecompleted_by_title` (`completed_by_title`); 
ALTER TABLE `t_mmrrc_order` ADD INDEX `Indexnameorder_submission_oid` (`order_submission_oid`); 
ALTER TABLE `t_mmrrc_order` ADD INDEX `Indexnameorder_dt` (`order_dt`); 
ALTER TABLE `t_mmrrc_order` ADD INDEX `Indexnamecenter_id` (`center_id`); 
ALTER TABLE `t_mmrrc_order` ADD INDEX `Indexnamepo_num_tx` (`po_num_tx`); 
ALTER TABLE `t_mmrrc_order` ADD INDEX `Indexnamemod_dt` (`mod_dt`); 
ALTER TABLE `t_mmrrc_order` ADD INDEX `Indexnameother_emails` (`other_emails`); 
ALTER TABLE `t_mmrrc_order` ADD INDEX `Indexnamecustomer_label` (`customer_label`); 
ALTER TABLE `t_mmrrc_order` ADD INDEX `Indexnamegrant_numbers` (`grant_numbers`); 
ALTER TABLE `t_distribution_contact ` ADD INDEX `Indexnamefirst_name` (`first_name`); 
ALTER TABLE `t_distribution_contact ` ADD INDEX `Indexnamelast_name` (`last_name`); 
ALTER TABLE `order_search` ADD INDEX `Indexnameproducts` (`products`); 
+0

感谢您的建议。我应用了索引,但仍然没有加速。 order_search实际上是一个视图,我发现这是造成大部分减速的原因。 我将编辑原始帖子并添加order_search视图查询。 – coder4life

+4

大部分索引都是无用的,因为涉及的列不在任何'WHERE'或'JOIN'子句中。 – dezso

+0

@dezso我已经添加了选择coloumns上的索引阅读我的上面的答案'仍然有很多coloumns像你的连接条件索引'我还没有提供所有的索引,所以仔细阅读这篇文章,然后评论谢谢 –