面向复杂查询的MySQL查询优化

面向复杂查询的MySQL查询优化,mysql,sql,optimization,query-optimization,Mysql,Sql,Optimization,Query Optimization,我正在使用一个现有站点,遇到了以下需要优化的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.s

我正在使用一个现有站点,遇到了以下需要优化的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秒以上的时间运行。无限制运行时,总共有5727个结果,运行时间为10.624秒

“限制0,5”花了18.47秒

我知道有很多连接和嵌套选择,这就是为什么它这么慢的原因。有没有关于如何在不改变数据库结构的情况下对此进行优化的想法

MySQL版本:5.0.95

大多数表都有超过10000条记录

这个简单的查询大约需要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秒。任何帮助都将不胜感激。谢谢

其他详细信息-以下是解释为第一个查询提供的信息:

我发现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

假设您还没有为冒号编制索引,那么我为冒号创建了一些索引,这会对您有所帮助,而且还有很多冒号需要编制索引,就像在连接条件中一样,您应该在冒号上应用此操作,以便更好地执行

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`);

通过从PHP脚本中执行两个单独的查询,我成功地解决了这个问题。 首先,我自己查询order_search视图,并将所有数据保存在一个由mmrrc_order_oid索引的PHP数组中,然后将其用作产品的快速查找表。由此产生的查找表是一个大约6000个字符串的数组


接下来,我将执行大型复杂查询,省略order_搜索表。现在只需要一秒钟。对于每个生成的记录,我只需使用mmrrc_order_oid的查找表来获取该订单的产品。

将能够告诉您更多有关此查询速度慢于我们的原因。谢谢,我添加了EXPLAIN的输出。仍然不确定如何优化。是否在列上添加了索引(如果已添加),请将其发布到视图中,是否加入
t\u train\u archive
只是为了测试是否存在相应的行?而且,至少从您更大的查询(实际上是视图上的任何其他查询)的角度来看,
ORDER BY
是不必要的。而且,出于好奇,您(或作者)为什么称明显的ID为
…\u oid
?谢谢您的建议。我应用了索引,但它仍然没有太多的加速。order_search实际上是一个视图,我发现这是导致大多数速度减慢的原因。我将编辑原始帖子并添加order_search view查询。你的大多数索引都是无用的,由于所涉及的列不在任何
WHERE
JOIN
子句中,因此我在select列上添加了索引阅读我的上述答案
仍有许多列需要索引,就像在您的连接条件中一样
我没有提供所有索引,因此请先仔细阅读文章,然后感谢注释:为每一列编制索引是没有用的。通常,只出现在
选择
列表中的列不会被索引,除非它是覆盖索引,但所有内容都应该在同一个复合索引中。这是一本关于如何索引和索引内容的非常好的读物。所以,好的,我将阅读链接以增加我对索引的了解,谢谢