优化SQL查询

clo*_*000 0 mysql sql performance time join

我有查询需要40秒才能执行,我想知道如何让它更快......

SELECT rp.`id` as rip,r.`id`, 
  rl.`id` as rlid, r.`number`, r.`type`, 
  a.`title` as atitle, a.`id` as aid, more, 
  more_valid 
FROM 
  `R_l_p` rp INNER JOIN 
  `Rl` rl ON rp.`rl_id` = rl.`id` INNER JOIN 
  `R` r ON r.`id` = rl.`r_id` INNER JOIN 
  `A` a ON a.`id` = r.`a_id` 
  LEFT JOIN 
   (SELECT `type`, `v`, `r_id`, COUNT(*) AS more 
    FROM `R_l` 
    WHERE `type` = 'stream' AND `v` = 1 
    GROUP BY `r_id`) stm ON stm.`r_id` = r.`id`
  LEFT JOIN 
   (SELECT `type`, `v`, `r_id`, COUNT(*) AS more_valid 
    FROM `R_l` 
    WHERE `type` = 'stream' AND `v` = 0 
    GROUP BY `r_id`) morelink ON morelink.`r_id` = r.`id`
WHERE rp.`link` = 'dead' AND rl.`type` = 'stream' 
ORDER BY rip ASC 
LIMIT 0, 1000
Run Code Online (Sandbox Code Playgroud)
+-----+--------------+---------------+---------+--------------------------+-------------+----------+---------------------------+--------+----------------------------------------------+
| id  | select_type  |    table      |  type   |      possible_keys       |    key      | key_len  |           ref             | rows   |                    Extra                     |
+-----+--------------+---------------+---------+--------------------------+-------------+----------+---------------------------+--------+----------------------------------------------+
|  1  | PRIMARY      | r             | ALL     | PRIMARY,a_id             | NULL        | NULL     | NULL                      | 21804  | Using temporary; Using filesort              |
|  1  | PRIMARY      | a             | eq_ref  | PRIMARY                  | PRIMARY     | 4        | db453988339.r.a_id        |     1  |                                              |
|  1  | PRIMARY      | rl            | ref     | PRIMARY,r_id,type        | r_id        | 4        | db453988339.r.id          |     1  | Using where                                  |
|  1  | PRIMARY      | derived2      | ALL     | NULL                     | NULL        | NULL     | NULL                      | 21077  |                                              |
|  1  | PRIMARY      | derived3      | ALL     | NULL                     | NULL        | NULL     | NULL                      |     1  |                                              |
|  1  | PRIMARY      | rp            | eq_ref  | rl_id                    | rl_id       | 4        | db453988339.rl.id         |     1  | Using where                                  |
|  3  | DERIVED      | R_link        | ALL     | type                     | NULL        | NULL     | NULL                      | 27580  | Using where; Using temporary; Using filesort |
|  2  | DERIVED      | R_link        | ALL     | type                     | NULL        | NULL     | NULL                      | 27580  | Using where; Using temporary; Using filesort |
+-----+--------------+---------------+---------+--------------------------+-------------+----------+---------------------------+--------+----------------------------------------------+

谢谢 :)

spe*_*593 5

对于一两件事,我会更换一个单列直插式视图,返回两个内嵌的意见more,并more_valid通过WHERE子句中的移动情况在公式中的SELECT列表),并消除来自同一个内嵌视图more_link视图.

我修改stm内联视图是这样的:

       ( SELECT q.r_id
              , SUM(q.v=1) AS `more`
              , SUM(q.v=0) AS `more_valid`
           FROM `R_l` q
          WHERE q.type = 'stream'
          GROUP BY q.r_id
       ) stm
Run Code Online (Sandbox Code Playgroud)

我还提供了一个覆盖索引来优化内联视图查询,例如:

    CREATE INDEX R_1_IX1 ON R_1 (type, r_id, v)
Run Code Online (Sandbox Code Playgroud)

使用前导列上的等式谓词type,MySQL可以使用索引优化GROUP BY操作(避免"使用filesort"操作).我们更愿意在解释的额外列中看到"使用索引".

不幸的是,派生表不会被编入索引.但至少在这种变化的情况下,您只能实现一个内联视图,避免额外的连接操作.


也就是说,我会替换这两行:

LEFT JOIN (SELECT `type`, `v`, `r_id`, COUNT(*) AS more FROM `R_l` WHERE `type` = 'stream' AND `v` = 1 GROUP BY `r_id`) stm ON stm.`r_id` = r.`id`
LEFT JOIN (SELECT `type`, `v`, `r_id`, COUNT(*) AS more_valid FROM `R_l` WHERE `type` = 'stream' AND `v` = 0 GROUP BY `r_id`) morelink ON morelink.`r_id` = r.`id`
Run Code Online (Sandbox Code Playgroud)

有了这个:

  LEFT
  JOIN ( SELECT q.r_id
              , SUM(q.v=1) AS `more`
              , SUM(q.v=0) AS `more_valid`
           FROM `R_l` q
          WHERE q.type = 'stream'
          GROUP BY q.r_id
       ) stm
    ON stm.r_id =  r.id
Run Code Online (Sandbox Code Playgroud)