Mysql 慢查询组与子查询连接

Posted

技术标签:

【中文标题】Mysql 慢查询组与子查询连接【英文标题】:Mysql Slow Query group concat with subquery 【发布时间】:2013-05-14 08:01:32 【问题描述】:

我有以下查询

select 
  `cs`.sku ,
  group_concat(
    IF(
        (
          (
            SELECT 
               count(id_catalog_category) 
            from 
               `catalog_category` 
            where 
               lft <= `ccg`.lft 
               and  rgt >= `ccg`.rgt
          )=2
       ),
       `ccg`.name_en,
       NULL
    )
) as level_1_categories
from 
  catalog_simple `cs` 
left join `catalog_config` `cc` 
  on `cs`.`fk_catalog_config` = `cc`.`id_catalog_config`
left join `catalog_config_has_catalog_category` `cchcc` 
  on `cc`.`id_catalog_config` = `cchcc`.`fk_catalog_config`
left join `catalog_category` `ccg` 
  on `cchcc`.`fk_catalog_category` = `ccg`.`id_catalog_category` 
group by `cc`.sku

Explain Extended 给出以下结果。

"id"    "select_type"   "table" "type"  "possible_keys" "key"   "key_len"   "ref"   "rows"  "filtered"  "Extra"
"1" "PRIMARY"   "cs"    "ALL"   NULL    NULL    NULL    NULL    "27384" "100.00"    "Using temporary; Using filesort"
"1" "PRIMARY"   "cc"    "eq_ref"    "PRIMARY"   "PRIMARY"   "4" "pkfas.cs.fk_catalog_config"    "1" "100.00"    ""
"1" "PRIMARY"   "cchcc" "ref"   "uk_id_catalog_config_has_catalog_category,fk_catalog_config"   "uk_id_catalog_config_has_catalog_category" "4" "pkfas.cc.id_catalog_config"    "2" "100.00"    "Using index"
"1" "PRIMARY"   "ccg"   "eq_ref"    "PRIMARY"   "PRIMARY"   "4" "pkfas.cchcc.fk_catalog_category"   "1" "100.00"    ""
"2" "DEPENDENT SUBQUERY"    "catalog_category"  "ALL"   "lft,rgt"   NULL    NULL    NULL    "1739"  "100.00"    "Using where"

执行此查询大约需要 100 秒

Sql Slow 有以下结果

Query_time: 95.189445  Lock_time: 0.000000 Rows_sent: 8523  Rows_examined: 242668622

请指导我如何使其快速。 提前致谢

【问题讨论】:

【参考方案1】:

查询的性能可以通过删除依赖子查询(对每一行执行)来实现,所以试试这个:

SELECT 
  `cs`.sku ,
  group_concat(
    IF(
       tmp.za_count = 2,
       `ccg`.name_en,
       NULL
    )
) as level_1_categories
FROM 
  catalog_simple `cs` 
LEFT JOIN `catalog_config` `cc` 
  ON `cs`.`fk_catalog_config` = `cc`.`id_catalog_config`
LEFT JOIN `catalog_config_has_catalog_category` `cchcc` 
  ON `cc`.`id_catalog_config` = `cchcc`.`fk_catalog_config`
LEFT JOIN (
    SELECT
      `ccg`.`id_catalog_category`,
      SUM(IF(`ccg1`.`id_catalog_category` IS NULL,0,1)) as za_count
    FROM `catalog_category` `ccg` 
      ON `cchcc`.`fk_catalog_category` = `ccg`.`id_catalog_category`
    LEFT JOIN `catalog_category` `ccg1` 
      ON `ccg1`.lft <= `ccg`.lft 
      AND  `ccg1`.rgt >= `ccg`.rgt
    GROUP BY
      `ccg`.`id_catalog_category`
) as tmp
    ON tmp.id_catalog_category = `cchcc`.`fk_catalog_category`
group by `cc`.sku

【讨论】:

Np :) 你能告诉我花了多少时间吗?你做了哪些修改? 这是最后的子查询。 SELECT ccg.id_catalog_category, SUM(IF(ccg1.id_catalog_category IS NULL,0,1)) as za_count FROM catalog_category ccg LEFT JOIN catalog_category id_catalog_category ON @9876 lft ccg.lft AND ccg1.rgt >= ccg.rgt GROUP BY ccg.id_catalog_category

以上是关于Mysql 慢查询组与子查询连接的主要内容,如果未能解决你的问题,请参考以下文章

MariaDB 连接查询与子查询

连接查询与子查询

从零开始学习MySql数据库函数与子查询和连接查询

数据库(比如MYSQL) ,表连结查询与子查询哪个效率高些? 为啥

MSSQL之五 连接查询与子查询

如何将查询与子查询连接起来?