2012-09-19 5 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 초입니다.

"LIMIT 0, 5"의 경우 18.47 초가 걸렸습니다.

많은 조인과 중첩 된 선택이 있다는 것을 알고 있습니다. 그래서 왜 그렇게 느립니다. 데이터베이스 구조를 변경하지 않고도이를 최적화하는 방법에 대한 아이디어가 있습니까?

MySQL 버전 : 5.0.95

대부분의 테이블이 10,000 개 이상의 기록을 가지고있다.

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 

나는 그룹이 가장 아래로 느려 가정 :

이 간단한 쿼리는 약 9 초 정도 걸립니다. 이 경우 그룹화하지 않고 단지 0.17 초 걸립니다. 어떤 도움을 주시면 감사하겠습니다. 감사.

추가 세부 사항 - 여기 EXPLAIN은 첫 번째 쿼리 나에게주는 무엇인가가 : View Image enter image description here

는 그 order_search 아래로 천천히 대부분의 원인이되는 도면이다 발견했다. 뷰에 대한 쿼리는 다음과 같습니다 그냥 당신이하지 인덱스 coloumns 그래서 난이 당신을 도울 것이다 당신의 coloumns에 대한 몇 가지 인덱스를 생성하고 같은 인덱스에 많은 coloumns 당신의 가입 조건에 거기에 여전히 가정

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

에 대해서도 coloumns에서이 작업을 적용 할 수 있습니다. 먼저 order_search 뷰를 쿼리하여 mmrrc_order_oid로 인덱싱 된 PHP 배열에 모든 데이터를 저장 한 다음 제품에 대한 빠른 검색 테이블로 사용합니다. 결과 조회 테이블은 약 6000 개의 문자열 배열입니다.

다음으로 order_search 테이블이 생략 된 큰 복잡한 쿼리를 수행합니다. 이것은 단지 1 초 정도 걸립니다. 결과 레코드마다 mmrrc_order_oid의 검색 테이블을 사용하여 해당 주문에 대한 제품을 얻습니다.

0

을 수행해야 그게 내가 내 PHP 스크립트에서 두 개의 쿼리를 수행하여이 문제를 해결하기 위해 관리 잘 실행

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 select coloumns에 색인을 추가했습니다. 위와 같은 대답을 읽었습니다.'조인 조건 에서처럼 색인을 생성 할 수있는 많은 coloumns가 있습니다. ''모든 색인을 제공하지 않기 때문에 먼저 게시물을주의 깊게 읽은 다음 감사합니다. –