或左连接

时间:2013-02-21 07:16:36

标签: mysql performance query-optimization left-join

广告牌表140000行,区域1000行。

SELECT 
    r.id,
    SUM(IF(bb.r1_id = r.id, 1, 0)) AS count,
    SUM(IF(bb.r2_id = r.id, 1, 0)) AS count2
FROM
    tmp_regions AS r
LEFT JOIN
    tmp_billboards AS bb
    ON (r.id = bb.r1_id OR r.id = bb.r2_id) 
WHERE
    bb.deleted = 0 
    AND
    bb.x != 0 
    AND
    bb.y != 0
GROUP BY r.id
ORDER BY r.capital DESC , r.other , r.name

执行时间是8秒

解释

id  select_type table   type    possible_keys   key key_len ref rows    Extra
1   SIMPLE  bb  ref bb_r,bb_deleted,bb_x,bb_y,deleted_x_y,bb_r2 bb_deleted  1   const   66396   Using where; Using temporary; Using filesort
1   SIMPLE  r   ALL PRIMARY NULL    NULL    NULL    1000    Using where; Using join buffer

如何更改OR以改善性能?

2 个答案:

答案 0 :(得分:0)

添加索引。 explain的输出显示了哪些字段需要它们。

答案 1 :(得分:0)

假设tmp_regions (id)是主键,您可以重写查询并将OR转换为2个连接:

SELECT 
    r.id,
    COALESCE(bb1.cnt, 0) AS count,
    COALESCE(bb2.cnt, 0) AS count2
FROM
    tmp_regions AS r
  LEFT JOIN
    ( SELECT r1_id, COUNT(*) AS cnt
      FROM tmp_billboards
      WHERE deleted = 0 
        AND x <> 0 
        AND y <> 0
      GROUP BY r1_id
    ) AS bb1
    ON r.id = bb1.r1_id
  LEFT JOIN
    ( SELECT r2_id, COUNT(*) AS cnt
      FROM tmp_billboards
      WHERE deleted = 0 
        AND x <> 0 
        AND y <> 0
      GROUP BY r2_id
    ) AS bb2
    ON r.id = bb2.r2_id
ORDER BY r.capital DESC , r.other , r.name ;

为提高效率,(deleted, r1_id, x, y)(deleted, r2_id, x, y)上的索引有助于避免tmp_billboards上的表扫描。