来源:安瑞哥是码农
就在我写完上一篇,Doris升级到2.0.2之后跟之前Doris1.2.3的查询效率对比文章后。
估计是对我这个新旧版本的对比结果不太满意,有社区的小伙伴私信告诉问我,测试2.0.2的时候,是否有用 ANALYZE 功能,并告诉我,它是2.0新优化器很重要的一个模块,目的就是加速查询用的。
然后扔给我一个相关的链接,我顺着这个链接点开一看,确实是一片陌生的内容,它位于官方文档的「查询加速」模块下,相比于我之前看到的1.2版本的文档,新的2.0又多了几个新花招。

1.2版本的加速功能

2.0新版本的加速功能
对比一下,从文档结构描述来看,2.0一下子多了4个新的查询加速功能,咱后续考虑一个个来测测看。
但今天,我们先把目光聚焦在这个统计信息,也就是对表的 ANALYZE 功能,看到底是怎么玩的?
0. 先看文档
既然是一项新功能,自然第一步就是看官方文档是怎么描述这玩意的。
这个推荐我去看的,表优化查询(查询加速)功能叫「统计信息」,打开文档一看呢,内容还挺多的,里面包含的信息量有些大。
老实说,这个文档内容虽然详尽,篇幅很长,但并没有到做到结构清晰、言简意赅(我个人认为),估计会让很多第一次阅读的同学没有耐心全部读完,我通读了两遍,现把我对这部分「统计信息」内容的理解,总结如下:
1,从文档结构中的命名来看,「统计信息」顾名思义就是对表中的数据进行各种基础信息、和共性属性的统计,因为Doris是列式数据库,所以这个统计,会对比如每一列数据的总条数、基数、最大值、最小值、空值情况等进行各种汇总;
2,这个统计,跟所有对数据库的查询进行优化的思想一样,本质就是预计算,将一些不需要跟业务规则强绑定的共性计算,提前给做了,为后续的业务查询尽可能提供加速便利;
3,这个所谓的统计信息,可以在后续基于业务的复杂查询时,为数据库的查询优化器,提供优化依据,生成最优查询计划。
那到底,这个所谓的「统计信息」是怎么玩的?以及它到底能不能真正实现我们的业务查询加速,我们还是老规矩,测试一下便知。
1. 先看怎么玩的
从文档的描述,以及结合我的实践来看,这个针对表的统计(ANALYZE),在新的版本里,必须要通过手动触发才可以,虽然文档的最后说这个full auto analyze功能是默认开启的。

但我通过在新的2.0集群中新建了一张表之后,并没有发现这个analyze有启动的迹象(我等了几个小时都没有启动,那这肯定不是自动的)。

对新建的表灌入数据后,并没有对其analyze
是我的姿势不对吗?还是确实不能这么玩?
此外呢,从文档描述中来看,说它还可以通过额外对表设置AUTO的方式,让其自动对表的数据进行统计(ANALYZE),设置方式如下:

可以看到,对应确实产生了一个后台的job id(截图部分没有显示出来),很快这个analyze就完成了。

看一眼这个analyze的统计结果:

表粒度的analyze结果

列粒度的analyze结果
但是,当我继续往这表里再写入一些数据时,按理说,既然这个 analyze 被设置为 auto 模式了,那我后续写数据进去,这个对于的统计结果应该要更新才对。
可是,它不,当我再次往里写入2w条记录数据时,这个统计结果依旧岿然不动。

往里再写2w条记录

多次执行,统计结果没有变化
尝试了几次,没招了。(PS:后续我又尝试用 period 和 incremental的配置方式,还是不行)
只能再次手动执行analyze命令,这才正常。

注意,这里之所以总数量少于3w(1w + 2w),原因在于后面写进去的2w数据跟之前的存在少量重复,而该表是个去重表模型导致。
但是,即便是这样,这个统计的结果依然存在槽点。
槽点1:
说好的,针对表粒度的统计结果,应该有6个字段的统计信息,但我这查询出来的,却只有3个。
官方文档给出的统计信息是这样的:

统计结果有6个字段
而我运行的统计信息,是这样的:

统计结果只有3个字段
谁能告诉我为什么?莫非我升级了个假的 2.0。
槽点2:
既然是统计(analyze),那咱是不是要统计准确一点?
那为毛用这种方式统计出来的一些结果,跟我直接用查询语句查出来的还不一样呢?

比如对于上面这张表来说,authority_record 这个字段的ndv值,也就是 count distinct 值为6291,但是我用SQL语句查出来,居然是6321。

不止这个字段,其他字段的这个ndv统计也都基本一个鸟样,就很迷。
疑点:
那既然这个analyze功能,只能通过每次需要时,去手动去触发(目前我看到是的),那它存在的意义有用多大呢?
莫非需要我额外再去写个脚本,去定期执行?而且它这个统计的信息很多都不准,我不知道到底能给这个查询优化器加多少速。
另外,以上还只是这个analyze功能,基于列的普通统计。
新版本的Doris说还支持对列的「直方图统计」,但是在我的这个集群里,却这么着都实现不了。
官方文档给的示例:

我集群的执行情况:

这又是啥情况呢?明明升级成功了呀。
2. 能真的对查询加速吗
既然说这个对表的 analyze,可以加速我们的业务查询,那咱来就来实际测试看看,到底是不是真的?
由于在实际的查询过程中,对于同一个查询SQL,即便排除任何外界因素影响下,其查询耗时也会有所波动,所以对于查询效率对比,只要差别不大,我们就暂且认为没有变化。
(PS:为了不让文章显得过于冗长,以下查询效率的截图就先不放了,直接给结论)
2.1 找出target_ip为空时(实际数据为双引号),此时每个不同domain的个数(要求domain统一小写)
查询SQL为:
select
domain,
count(domain) as count
from
(
select
lower(domain) as domain
from
logs_from_spark01
where target_ip='""'
)t
group by
t.domain;
开启analyze前后,几乎没有变化。
2.2 查询上网次数最多的前100个client_ip,以及他们分别的归属地是哪里
查询SQL如下:
select
t1.client_ip,
t2.nature,
t2.province,
t2.city,
t1.count
from
(
select
client_ip,
count(client_ip) as count
from
logs_from_spark01
group by
client_ip
order by
count desc
limit 100
)t1
inner join
logs_from_spark01 t2
on
t1.client_ip=t2.client_ip
group by
client_ip,
nature,
province,
city,
count
开启analyze前后,几乎没有变化。
2.3 count distinct的效率对比
查询SQL:
select
client_ip,
max(row_num2) as max
from
(
select
client_ip,
row_num2,
date_min
from
(
select
client_ip,
sub_date,
row_number() over (partition by client_ip,sub_date) as row_num2,
date_min
from
(
select
client_ip,
date_min,
row_number() over (partition by client_ip order by date_min) as row_num,
minutes_sub(to_date(date_min), row_num) as sub_date
from
(
select client_ip,
date_min,
row_number() over (partition by client_ip,date_min order by date_min) as row_num
from
(
select
client_ip,
minute_floor(time) AS date_min
from
logs_from_spark01
where
length(time)=14
and
time like '20220730%'
)t
) A
where A.row_num=1
) B
) C
)D
group by
D.client_ip
order by max desc
limit 100
开启analyze前后,查询效率没有变化。
2.5 查询出 client_ip 中包含的所有国家、省份、城市,以及运营商
查询SQL:
select
nature,
province,
city,
operator
from
logs_from_spark01
group by
nature,
province,
city,
operator;
开启analyze前后,查询效率几乎没有变化。
2.6 查询表中不重复数据的数据总条数
查询SQL:
SELECT
count(*)
FROM
(
SELECT
*,
row_number() over (partition by client_ip, nature, province, city, operator, domain, time, target_ip, rcode, query_type, authority_record, add_msg, dns_ip) as row_num
FROM
logs_from_spark01
)t
WHERE t.row_num =1;
开启analyze前后,查询效率几乎没有变化(甚至慢了一丢丢)。