优化派生子查询性能将不同的记录拉入 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
。
在此查询中 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
。