2012-04-20 5 views
0

일부 조인이 포함 된 쿼리가 있습니다. 이 쿼리에서 조인 한 모든 테이블에는 외래 키가 있습니다. 실행 시간은 매우 느립니다. 약 23 초입니다. 주 테이블에는 약 50,000 개의 행이 있습니다. 여기MySql 쿼리가 느린 데이터 전송

SELECT o.id, o.title, o.link, o.position_id, o.status, o.publish_date, o.archived_on, vos.name AS site_name, vorib.image AS ribbon, vop.picture, 
      GROUP_CONCAT(DISTINCT CAST(voci.name AS CHAR)) AS cities, 
      GROUP_CONCAT(DISTINCT CAST(vors.name AS CHAR)) AS regions, 
      GROUP_CONCAT(DISTINCT CAST(voi.icon_id AS CHAR)) AS icons, 
       GROUP_CONCAT(DISTINCT CAST(voc.city_id AS CHAR)) AS cities_id, 
      GROUP_CONCAT(DISTINCT CAST(vor.region_id AS CHAR)) AS regions_id, 
      GROUP_CONCAT(DISTINCT CAST(vose.section_id AS CHAR)) AS sections, 
      GROUP_CONCAT(DISTINCT CAST(vocat2.category_id AS CHAR)) AS categories, 
      GROUP_CONCAT(DISTINCT CAST(vocategories.name AS CHAR)) AS categories_names,   
      (SELECT SUM(vocount.clicks) FROM vo_offers_counter AS vocount WHERE vocount.offer_id = vo.id) AS hits 
     FROM vo_offers AS o 
       LEFT JOIN offers_pictures AS vop ON o.id = vop.offer_id AND vop.number = 1 
       LEFT JOIN offer_sites AS vos ON o.site_id = vos.id 
       LEFT JOIN offers_city AS voc ON o.id = voc.offer_id 
       LEFT JOIN offers_category AS vocat ON o.id = vocat.offer_id 
       LEFT JOIN offers_category AS vocat2 ON o.id = vocat2.offer_id 
       LEFT JOIN offer_categories AS vocategories ON vocat2.category_id = vocategories.id 
       LEFT JOIN offers_city AS voc2 ON o.id = voc2.offer_id 
       LEFT JOIN offer_cities AS voci ON voc2.city_id = voci.id 
       LEFT JOIN offers_region AS vor ON o.id = vor.offer_id 
       LEFT JOIN offer_regions AS vors ON vor.region_id = vors.id 
       LEFT JOIN offer_ribbons AS vorib ON o.ribbon_id = vorib.id 
       LEFT JOIN offers_section AS vose ON o.id = vose.offer_id 
       LEFT JOIN offers_icons AS voi ON o.id = voi.offer_id 
       WHERE o.id IS NOT NULL AND o.status IN ('published','pending','xml') 
GROUP BY o.id 
ORDER BY CASE WHEN o.position_id IN('', '0') THEN ~0 ELSE 0 END asc, o.position_id asc, o.publish_microtime desc 
LIMIT 100 OFFSET 200 

는 쿼리의 DESCRIBE입니다 :

+----+--------------------+--------------+--------+---------------------------+---------------------------+---------+--------------------------------------+------+----------------------------------------------+ 
    | id | select_type  | table  | type | possible_keys    | key      | key_len | ref         | rows | Extra          | 
    +----+--------------------+--------------+--------+---------------------------+---------------------------+---------+--------------------------------------+------+----------------------------------------------+ 
    | 1 | PRIMARY   | o   | range | PRIMARY,status   | status     | 2  | NULL         | 3432 | Using where; Using temporary; Using filesort | 
    | 1 | PRIMARY   | vop   | ref | offer_id     | offer_id     | 5  | new_vsichkioferti.v.id    | 1 |            | 
    | 1 | PRIMARY   | vos   | eq_ref | PRIMARY     | PRIMARY     | 4  | new_vsichkioferti.v.site_id   | 1 |            | 
    | 1 | PRIMARY   | voc   | ref | offer_id     | offer_id     | 5  | new_vsichkioferti.v.id    | 2 | Using index         | 
    | 1 | PRIMARY   | vocat  | ref | vo_offers_category_ibfk_1 | vo_offers_category_ibfk_1 | 5  | new_vsichkioferti.v.id    | 1 | Using index         | 
    | 1 | PRIMARY   | vocat2  | ref | vo_offers_category_ibfk_1 | vo_offers_category_ibfk_1 | 5  | new_vsichkioferti.v.id    | 1 |            | 
    | 1 | PRIMARY   | vocategories | eq_ref | PRIMARY     | PRIMARY     | 4  | new_vsichkioferti.vocat2.category_id | 1 | Using index         | 
    | 1 | PRIMARY   | voc2   | ref | offer_id     | offer_id     | 5  | new_vsichkioferti.v.id    | 2 |            | 
    | 1 | PRIMARY   | voci   | eq_ref | PRIMARY     | PRIMARY     | 4  | new_vsichkioferti.voc2.city_id  | 1 | Using index         | 
    | 1 | PRIMARY   | vor   | ref | offer_id     | offer_id     | 5  | new_vsichkioferti.v.id    | 1 |            | 
    | 1 | PRIMARY   | vors   | eq_ref | PRIMARY     | PRIMARY     | 4  | new_vsichkioferti.vor.region_id  | 1 | Using index         | 
    | 1 | PRIMARY   | vorib  | eq_ref | PRIMARY     | PRIMARY     | 4  | new_vsichkioferti.v.ribbon_id  | 1 |            | 
    | 1 | PRIMARY   | vose   | ref | offer_id     | offer_id     | 5  | new_vsichkioferti.v.id    | 1 | Using index         | 
    | 1 | PRIMARY   | voi   | ref | offer_id     | offer_id     | 5  | new_vsichkioferti.v.id    | 1 | Using index         | 
    | 2 | DEPENDENT SUBQUERY | vocount  | ref | offer_id     | offer_id     | 5  | func         | 1 | Using where         | 
    +----+--------------------+--------------+--------+---------------------------+---------------------------+---------+--------------------------------------+------+----------------------------------------------+ 
    15 rows in set 

이 빠르게 실행 얻을 내가 무엇을 할 수 있는가?

[편집]

문제는이 조인되어에서 : 인덱스와 모두 OFFER_ID 및 CITY_ID :

LEFT JOIN offers_city AS voc2 ON o.id = voc2.offer_id 
LEFT JOIN offer_cities AS voci ON voc2.city_id = voci.id 

대부분 처음에, 테이블 offers_city가 있지만이 열 221339 행을 함께 외래 키입니다

+0

일반적으로 "파일 포트 사용"은 문제를 나타내는 지표입니다. 'ORDER BY'에서'CASE'를 제거하는 것이 도움이됩니까? 쿼리가 실행될 때마다 정렬하기 전에 모든 행에 대해 해당 식을 계산해야하기 때문입니다. – DCoder

답변

2

나는 거기에서 메인 테이블 (vo_offers AS o) 열로 필터링합니다. 항상 그렇다면 하위 선택으로 속도를 높일 수 있습니다. 귀하의 쿼리와 함께 - 그것은 (아마도, 100 % 확실하지 않습니다) 먼저 조인 테이블에서 다른 모든 레코드를 조인하고 필터링을 수행합니다. 당신이 정말로 필요로하는 기록을 찾아 첫 번째 (하위 선택에서) 그래서이 경우 당신에

SELECT o.id, o.title, o.link, o.position_id, o.status, o.publish_date, o.archived_on, vos.name AS site_name, vorib.image AS ribbon, vop.picture, 
      GROUP_CONCAT(DISTINCT CAST(voci.name AS CHAR)) AS cities, 
      GROUP_CONCAT(DISTINCT CAST(vors.name AS CHAR)) AS regions, 
      GROUP_CONCAT(DISTINCT CAST(voi.icon_id AS CHAR)) AS icons, 
       GROUP_CONCAT(DISTINCT CAST(voc.city_id AS CHAR)) AS cities_id, 
      GROUP_CONCAT(DISTINCT CAST(vor.region_id AS CHAR)) AS regions_id, 
      GROUP_CONCAT(DISTINCT CAST(vose.section_id AS CHAR)) AS sections, 
      GROUP_CONCAT(DISTINCT CAST(vocat2.category_id AS CHAR)) AS categories, 
      GROUP_CONCAT(DISTINCT CAST(vocategories.name AS CHAR)) AS categories_names,   
      (SELECT SUM(vocount.clicks) FROM vo_offers_counter AS vocount WHERE vocount.offer_id = vo.id) AS hits 
     FROM (SELECT * FROM vo_offers WHERE id IS NOT NULL AND status IN ('published','pending','xml')) AS o 
       LEFT JOIN offers_pictures AS vop ON o.id = vop.offer_id AND vop.number = 1 
       LEFT JOIN offer_sites AS vos ON o.site_id = vos.id 
       LEFT JOIN offers_city AS voc ON o.id = voc.offer_id 
       LEFT JOIN offers_category AS vocat ON o.id = vocat.offer_id 
       LEFT JOIN offers_category AS vocat2 ON o.id = vocat2.offer_id 
       LEFT JOIN offer_categories AS vocategories ON vocat2.category_id = vocategories.id 
       LEFT JOIN offers_city AS voc2 ON o.id = voc2.offer_id 
       LEFT JOIN offer_cities AS voci ON voc2.city_id = voci.id 
       LEFT JOIN offers_region AS vor ON o.id = vor.offer_id 
       LEFT JOIN offer_regions AS vors ON vor.region_id = vors.id 
       LEFT JOIN offer_ribbons AS vorib ON o.ribbon_id = vorib.id 
       LEFT JOIN offers_section AS vose ON o.id = vose.offer_id 
       LEFT JOIN offers_icons AS voi ON o.id = voi.offer_id 
GROUP BY o.id 
ORDER BY CASE WHEN o.position_id IN('', '0') THEN ~0 ELSE 0 END asc, o.position_id asc, o.publish_microtime desc 
LIMIT 100 OFFSET 200 

만 다음의 경우

확실하지 다른 모든 테이블을 조인 :

그래서 당신은 뭔가를 시도 할 수 도움이 될 것이지만 최소한 시도해보십시오.

+0

해답을 가져 주셔서 감사합니다. 그러나 성능에는 전혀 차이가 없습니다. –

+0

모든 조인을 꺼내고 어느 위치에서 느리게 진행되는지보기 위해 1을 1로 되돌리려 고 시도 했습니까? 메인 테이블에서 선택하는 것이 그렇게 느리지 않아야한다고 생각합니다 ... – Laimoncijus

관련 문제