1

私は既存のサイトで作業していますが、最適化が必要な次の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秒です。

「LIMIT0、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秒です。どんな助けでもいただければ幸いです。ありがとう。

追加の詳細-これがEXPLAINが最初のクエリに対して私に与えるものです: 画像を表示 ここに画像の説明を入力してください

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
4

2 に答える 2

0

PHPスクリプトから2つの別々のクエリを実行することで、この問題を解決することができました。まず、order_searchビューを単独でクエリし、mmrrc_order_oidでインデックス付けされたPHP配列にすべてのデータを保存します。これは、製品のクイックルックアップテーブルとして機能します。この結果のルックアップテーブルは、約6000個の文字列の配列です。

次に、order_searchテーブルを省略して大きな複雑なクエリを実行します。これには約1秒しかかかりません。結果のレコードごとに、mmrrc_order_oidによるルックアップテーブルを使用して、その注文の製品を取得します。

于 2012-09-26T21:20:11.750 に答える
0

列にインデックスを付けていないと仮定して、列にいくつかのインデックスを作成すると、これが役立ちます。結合条件のように、インデックスを作成する列がまだたくさんあるため、実行を改善するために、その列にもこの操作を適用する必要があります

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`);
于 2012-09-24T06:29:06.270 に答える