如何使用多个连接和子查询优化此慢查询

时间:2014-07-17 15:59:31

标签: mysql optimization explain

我必须优化其他人写的查询,我正在努力。它有时需要超过12秒才能完成!

我有一个SQL小提琴here,但是还没有数据。我认为数据量的部分原因是速度缓慢(在wed_supplies + postcodes中为20k,在注释中为60k),以及num_reviewsavg_rating子查询。

取出子查询会将其缩小到更接近2秒的时间,但我需要它们提供的值,并且它还需要更快。

SELECT *, c_title AS category,

        (SELECT COUNT(*) FROM comments WHERE site_id = '96' AND ec_type = 'review' AND ec_link_id = ws_id) AS num_reviews,
        (SELECT AVG(ec_rating) FROM comments WHERE site_id = '96' AND ec_type = 'review' AND ec_link_id = ws_id) AS avg_rating,
        (((acos(sin(( 52.1528253 *pi()/180)) * sin((`p_lat`*pi()/180))
            +cos(( 52.1528253 *pi()/180)) * cos((`p_lat`*pi()/180))
            * cos((( -0.6800496 - `p_lng`)*pi()/180))))*180/pi())*60*1.1515)
            AS distance
        FROM wed_suppliers 
            LEFT JOIN postcodes ON p_postcode = REPLACE(ws_postcode, ' ', '')
            LEFT JOIN c_content ON ws_category = c_id
        WHERE wed_suppliers.site_id = '96' AND c_content.site_id = '96'
        AND ws_hide = '0'
        AND ws_permalink != ''
        AND p_lat != '' AND p_lng != '' AND p_invalid = '0'
        HAVING distance <= 10

        ORDER BY distance ASC
        LIMIT 0,20

EXPLAIN

id  select_type     table   type    possible_keys   key     key_len     ref     rows    Extra
1   PRIMARY     wed_suppliers   range   ws_permalink,site_id,ws_category,ws_hide    site_id     4   NULL    22628   Using where; Using temporary; Using filesort
1   PRIMARY     postcodes   eq_ref  PRIMARY,p_invalid,p_lng,p_lat   PRIMARY     12  func    1   Using where
1   PRIMARY     c_content   eq_ref  PRIMARY,site_id     PRIMARY     4   engine_4.wed_suppliers.ws_category  1   Using where
3   DEPENDENT SUBQUERY  comments    index_merge     site_id,ec_link_id,ec_type  site_id,ec_type     4,34    NULL    1   Using intersect(site_id,ec_type); Using where
2   DEPENDENT SUBQUERY  comments    index_merge     site_id,ec_link_id,ec_type  site_id,ec_type     4,34    NULL    1   Using intersect(site_id,ec_type); Using where

我使用了EXPLAIN返回的this glossary,但没有太多运气。

如何优化此查询以使其以更合理的速度运行?以及如何将EXPLAIN转换为更有用的内容。

1 个答案:

答案 0 :(得分:1)

看起来您的联接正在使用索引。这留下了子查询:

    (SELECT COUNT(*) FROM comments WHERE site_id = '96' AND ec_type = 'review' AND ec_link_id = ws_id) AS num_reviews,
    (SELECT AVG(ec_rating) FROM comments WHERE site_id = '96' AND ec_type = 'review' AND ec_link_id = ws_id) AS avg_rating,

我建议使用以下复合索引:comments(ec_link_id, ec_type, site_id)。这应该加快子查询。