0

广告牌表 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 in join 以提高性能?

4

2 回答 2

1

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

于 2013-02-21T07:38:13.720 回答
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.

于 2013-02-21T07:41:22.410 回答