优化派生子查询性能将不同的记录拉入 group_concat()

optimizing derived-subquery performance pulling distinct records into a group_concat()

在此查询中 https://www.db-fiddle.com/f/wi525XMRAff2GHUrBpWAM8/5

select x.`id`, (
  select
    group_concat(d.`content`)
  from (
    select
      docs.`content`
    from
      `docs`
    where
      docs.`x_id` = 1
    group by
      docs.`content`
   ) as `d`
) as `letters`
from `x`
where x.`id` = 1;

我应该从 x table 中提取 x.id 以及 [=36 中的字母=]docs table 使用 docs.x_id 链接一次,这就是为什么我使用静态 x.id = 1

docs table中的字母可以重复为相同的x_id所以我想把它拉出来很明显,所以我选择了 标量查询 但是查询可以得到更优化吗?

我正在使用最新的 mariadb 版本并给我 extra: Using index; Using temporary; Using filesort 与 fiddle 中的版本不同显示 extra: Using index condition; Using temporary


我也试过使用这个查询https://www.db-fiddle.com/f/wi525XMRAff2GHUrBpWAM8/4

select x.`id`, group_concat(d.`content`) as `letters`
from `x`
inner join (
  select
    d.`x_id`, d.`content`
  from
    `docs` d
  where
    d.`x_id` = 1
  group by
    d.`x_id`, d.`content`
) d ON d.`x_id` = 1
where x.`id` = 1;

这为 mysql 8 提供了更好的执行计划结果,但在 mariadb (mysql 5.5.5) 与第一个查询的结果相同

我会尝试:

select x.`id`, 
       (select group_concat(distinct d.`content`)
        from docs
        where docs.`x_id` = 1
       ) as `letters`
from `x`
where x.`id` = 1;

更简单:

SELECT  1 AS id,
        GROUP_CONCAT(DISTINCT content) AS letters
    FROM  docs
    WHERE  x_id = 1

但是,我怀疑您过度简化了查询。所以这种简化可能并不完全适用。

无论如何,尽量不要把"subquery"当成解决问题的方法。请注意您需要 2 个子查询,但我在 0 中完成了它。而且它可能快得多。

为了进一步加速,将 INDEX(x_id) 更改为 INDEX(x_id, content)

"Using filesort"和"Using temporary"不是世界末日。在某些查询中,它们是绝对必要的。此外,"filesort" 通常在 RAM 中完成;在此查询的拍摄过程中没有磁盘受伤。我认为我的查询 INDEX 无论如何都要避免它们。

注意:默认 GROUP_CONCAT 限制为 1024。参见 group_concat_max_len