2012-04-20 18 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 

私はこれを高速に実行するために取得するために何ができますか?

[EDIT]

問題は、この中では、参加:

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行であるが、2つのだけの列を持つ:OFFER_IDとCITY_IDインデックスとの両方と外部キーです

+0

通常、「ファイル使用」は問題の指標です。 'CASE'を' ORDER BY'から削除するのは助けになりますか?その式は、照会が実行されるたびにソートする前にすべての行について計算する必要があるためです。 – 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

関連する問題