MySQL是否在相关表上优化所选聚合以避免N+;1.

MySQL是否在相关表上优化所选聚合以避免N+;1.,mysql,query-optimization,correlated-subquery,Mysql,Query Optimization,Correlated Subquery,这个查询在MySQL中是最优的吗?我的意思是:执行的查询数量是否恒定 还是属于N+1问题?在官方MySQL文档中没有发现任何关于优化的详细信息 SELECT t.*, (SELECT COUNT(1) from related_table rt where rt.t_id = t.id) FROM table t 简单地说,有一个查询和N个查询,所以它属于N+1问题 MySQL 5.5+是否自动地+在内部改进了这个查询,使查询数量保持不变?也许在内部将其转换为: SELECT t.*, COU

这个查询在MySQL中是最优的吗?我的意思是:执行的查询数量是否恒定

还是属于N+1问题?在官方MySQL文档中没有发现任何关于优化的详细信息

SELECT t.*, (SELECT COUNT(1) from related_table rt where rt.t_id = t.id)
FROM table t
简单地说,有一个查询和N个查询,所以它属于N+1问题

MySQL 5.5+是否自动地+在内部改进了这个查询,使查询数量保持不变?也许在内部将其转换为:

SELECT t.*, COUNT(rt.id)
FROM table t LEFT OUTER JOIN related_table rt
GROUP BY t.id
我的意思是:我知道如何手工改进,但我问这个是因为:

  • 也许通过一个库使用一个(不完全的IMHO)ORM对一个框架进行赋值
  • 好奇。在官方MySQL文档中找不到那么多文档

  • 不,选择列表中的相关子查询没有被MySQL优化

    您可以通过使用EXPLAIN获得优化计划的报告来确认这一点。下面是一个使用测试数据库的类似查询:

    mysql> explain select *, (SELECT COUNT(*) FROM cast_info where cast_info.role_id = role_type.id) AS c 
        from role_type\G
    *************************** 1. row ***************************
               id: 1
      select_type: PRIMARY
            table: role_type
       partitions: NULL
             type: index
    possible_keys: NULL
              key: role
          key_len: 98
              ref: NULL
             rows: 12
         filtered: 100.00
            Extra: Using index
    *************************** 2. row ***************************
               id: 2
      select_type: DEPENDENT SUBQUERY
            table: cast_info
       partitions: NULL
             type: ref
    possible_keys: cr
              key: cr
          key_len: 4
              ref: imdb.role_type.id
             rows: 2534411
         filtered: 100.00
            Extra: Using index
    
    依赖子查询的select类型意味着子查询将执行多次,可能对外部查询的每一行执行一次

    与手动优化查询的解释进行比较:

    mysql> explain select r.*, COUNT(c.id) AS c from role_type AS r  left outer join cast_info as c on r.id = c.role_id group by r.id\G
    *************************** 1. row ***************************
               id: 1
      select_type: SIMPLE
            table: r
       partitions: NULL
             type: index
    possible_keys: PRIMARY,role
              key: PRIMARY
          key_len: 4
              ref: NULL
             rows: 12
         filtered: 100.00
            Extra: NULL
    *************************** 2. row ***************************
               id: 1
      select_type: SIMPLE
            table: c
       partitions: NULL
             type: ref
    possible_keys: cr
              key: cr
          key_len: 4
              ref: imdb.r.id
             rows: 2534411
         filtered: 100.00
            Extra: Using index
    
    这表明对第二个表的访问只是一个简单的引用联接

    您还可以使用进行测试。下面是第二个查询,它使用join:

    +----------------------+----------+
    | Status               | Duration |
    +----------------------+----------+
    | starting             | 0.000167 |
    | checking permissions | 0.000015 |
    | checking permissions | 0.000016 |
    | Opening tables       | 0.000050 |
    | init                 | 0.000059 |
    | System lock          | 0.000044 |
    | optimizing           | 0.000011 |
    | statistics           | 0.000151 |
    | preparing            | 0.000099 |
    | Sorting result       | 0.000019 |
    | executing            | 0.000010 |
    | Sending data         | 9.700879 |
    | end                  | 0.000024 |
    | query end            | 0.000022 |
    | closing tables       | 0.000017 |
    | freeing items        | 0.000243 |
    | cleaning up          | 0.000056 |
    +----------------------+----------+
    
    这是一个具有从属子查询的查询:

    +----------------------+----------+
    | Status               | Duration |
    +----------------------+----------+
    | starting             | 0.000152 |
    | checking permissions | 0.000014 |
    | checking permissions | 0.000013 |
    | Opening tables       | 0.000050 |
    | init                 | 0.000067 |
    | System lock          | 0.000042 |
    | optimizing           | 0.000010 |
    | statistics           | 0.000367 |
    | preparing            | 0.000033 |
    | optimizing           | 0.000015 |
    | statistics           | 0.000032 |
    | preparing            | 0.000020 |
    | executing            | 0.000010 |
    | Sending data         | 0.000191 |
    | executing            | 0.000010 |
    | Sending data         | 4.103899 |
    | executing            | 0.000018 |
    | Sending data         | 2.413570 |
    | executing            | 0.000018 |
    | Sending data         | 0.043924 |
    | executing            | 0.000022 |
    | Sending data         | 0.037834 |
    | executing            | 0.000020 |
    | Sending data         | 0.014127 |
    | executing            | 0.000021 |
    | Sending data         | 0.089977 |
    | executing            | 0.000023 |
    | Sending data         | 0.045968 |
    | executing            | 0.000024 |
    | Sending data         | 0.000044 |
    | executing            | 0.000005 |
    | Sending data         | 0.190935 |
    | executing            | 0.000034 |
    | Sending data         | 1.046394 |
    | executing            | 0.000018 |
    | Sending data         | 0.017567 |
    | executing            | 0.000021 |
    | Sending data         | 0.882959 |
    | end                  | 0.000046 |
    | query end            | 0.000023 |
    | closing tables       | 0.000018 |
    | freeing items        | 0.000248 |
    | cleaning up          | 0.000025 |
    +----------------------+----------+
    

    您可以看到子查询导致多个执行。在我的例子中,role_type表中只有几行,但如果有数百行或数千行,子查询执行的数量可能会太长,以至于探查器会截断该报告。

    我看不出引用的问题是如何重复的,因为它涉及到
    中的
    。如果您想知道MySQL如何处理查询,请了解
    explain
    。您的两个查询将有不同的执行路径。谢谢:D我今天将检查它。请停止
    SELECT t.*。。。按t.id分组
    。它仍在创建依赖子查询