Doris-查询(三)

2023-11-12

1、查询设置

1.1、增大内存

一个查询任务,在单个 BE 节点上默认使用不超过 2GB 内存,内存不够时, 查询可能
会出现‘Memory limit exceeded’。

SHOW VARIABLES LIKE “%mem_limit%”;

exec_mem_limit 的单位是 byte,可以通过 SET 命令改变 exec_mem_limit 的值。如改
为 8GB。

SET exec_mem_limit = 8589934592;

上述设置仅仅在当前 session 有效, 如果想永久有效, 需要添加 global 参数。
SET GLOBAL exec_mem_limit = 8589934592;

1.2、修改超时时间

doris 默认最长查询时间为 300s, 如果仍然未完成, 会被 cancel 掉,查看配置:

SHOW VARIABLES LIKE “%query_timeout%”;

可以修改为 60s

SET query_timeout = 60;

同样, 如果需要全局生效需要添加参数 global。

set global query_timeout = 60;

当前超时的检查间隔为 5 秒,所以小于 5 秒的超时不会太准确。

1.3、查询重试和高可用

当部署多个 FE 节点时,用户可以在多个 FE 之上部署负载均衡层来实现 Doris 的高
可用。

1.3.1 代码方式

自己在应用层代码进行重试和负载均衡。比如发现一个连接挂掉,就自动在其他连接上
进行重试。应用层代码重试需要应用自己配置多个 doris 前端节点地址。

1.3.2 JDBC Connector

如果使用 mysql jdbc connector 来连接 Doris,可以使用 jdbc 的自动重试机制:

jdbc:mysql://[host1][:port1],[host2][:port2][,[host3][:port3]]...
[/[database]][?propertyName1=propertyValue1[&propertyName2=proper
tyValue2]...]

1.3.3 ProxySQL 方式

ProxySQL 是灵活强大的 MySQL 代理层, 是一个能实实在在用在生产环境的 MySQL 中
间件,可以实现读写分离,支持 Query 路由功能,支持动态指定某个 SQL 进行 cache,支持动态加载配置、故障切换和一些 SQL 的过滤功能。

Doris 的 FE 进程负责接收用户连接和查询请求,其本身是可以横向扩展且高可用的,
但是需要用户在多个 FE 上架设一层 proxy,来实现自动的连接负载均衡。

1)安装 ProxySQL (yum 方式)

配置 yum 源
#vim /etc/yum.repos.d/proxysql.repo
[proxysql_repo]
name= ProxySQL YUM repository
baseurl=http://repo.proxysql.com/ProxySQL/proxysql-
1.4.x/centos/\$releasever
gpgcheck=1
gpgkey=http://repo.proxysql.com/ProxySQL/repo_pub_key
执行安装
#yum clean all
#yum makecache
#yum -y install proxysql
查看版本 
#proxysql --version
设置开机自启动
#systemctl enable proxysql
#systemctl start proxysql 
#systemctl status proxysql
启动后会监听两个端口, 默认为 603260336032 端口是 ProxySQL 的管理端口,
6033 是 ProxySQL 对外提供服务的端口 (即连接到转发后端的真正数据库的转发端口)#netstat -tunlp

2)ProxySQL 配置
ProxySQL 有配置文件 /etc/proxysql.cnf 和配置数据库文件/var/lib/proxysql/proxysql.db。
这里需要特别注意:如果存在如果存在"proxysql.db"文件(在/var/lib/proxysql 目录下),则ProxySQL 服务只有在第一次启动时才会去读取 proxysql.cnf 文件并解析;后面启动会就不会读取 proxysql.cnf 文件了!如果想要让 proxysql.cnf 文件里的配置在重启 proxysql 服务后生效(即想要让 proxysql 重启时读取并解析 proxysql.cnf 配置文件),则需要先删除/var/lib/proxysql/proxysql.db 数据库文件,然后再重启 proxysql 服务。这样就相当于初始化启动 proxysql 服务了,会再次生产一个纯净的 proxysql.db 数据库文件(如果之前配置了proxysql 相关路由规则等,则就会被抹掉)
(1)查看及修改配置文件:主要是几个参数,在下面已经注释出来了,可以根据自己
的需要进行修改

#vim /etc/proxysql.cnf
datadir="/var/lib/proxysql" #数据目录
admin_variables=
{
 admin_credentials="admin:admin" #连接管理端的用户名与密码
 mysql_ifaces="0.0.0.0:6032" #管理端口,用来连接 proxysql 的管
理数据库
}
mysql_variables=
{
 threads=4 #指定转发端口开启的线程数量
 max_connections=2048
 default_query_delay=0
 default_query_timeout=36000000
 have_compress=true
 poll_timeout=2000
 interfaces="0.0.0.0:6033" #指定转发端口,用于连接后端 mysql 数
据库的,相当于代理作用
 default_schema="information_schema"
 stacksize=1048576
 server_version="5.7.28" #指定后端 mysql 的版本
 connect_timeout_server=3000
 monitor_username="monitor"
 monitor_password="monitor"
monitor_history=600000
 monitor_connect_interval=60000
 monitor_ping_interval=10000
 monitor_read_only_interval=1500
 monitor_read_only_timeout=500
 ping_interval_server_msec=120000
 ping_timeout_server=500
 commands_stats=true
 sessions_sort=true
 connect_retries_on_failure=10
}
mysql_servers =
(
)
mysql_users:
(
)
mysql_query_rules:
(
)
scheduler=
(
)
mysql_replication_hostgroups=
(
)

(2)连接 ProxySQL 管理端口测试

#mysql -h 127.0.0.1 -P 6032 -u admin -p
查看 main 库(默认登陆后即在此库)的 global_variables 表信息
show databases;
use main;
show tables;

(3)ProxySQL 配置后端 Doris FE
使用 insert 语句添加主机到 mysql_servers 表中,其中:hostgroup_id 为 10 表示写组,
为 20 表示读组,我们这里不需要读写分离,无所谓随便设置哪一个都可以。

mysql -u admin -p admin -P 6032 -h 127.0.0.1
insert into mysql_servers(hostgroup_id,hostname,port) 
values(10,'192.168.8.101',9030); 
insert into mysql_servers(hostgroup_id,hostname,port) 
values(10,'192.168.8.102',9030);
insert into mysql_servers(hostgroup_id,hostname,port) 
values(10,'192.168.8.103',9030);
如果在插入过程中,出现报错:
ERROR 1045 (#2800): UNIQUE constraint failed: 
mysql_servers.hostgroup_id, mysql_servers.hostname, 
mysql_servers.port
说明可能之前就已经定义了其他配置,可以清空这张表 或者 删除对应 host 的配置
select * from mysql_servers;
delete from mysql_servers;
查看这 3 个节点是否插入成功,以及它们的状态。
select * from mysql_servers\G;
 
如上修改后,加载到 RUNTIME,并保存到 disk,下面两步非常重要,不然退出以后配置信
息就没了,必须保存
load mysql servers to runtime;
save mysql servers to disk;

(4)监控 Doris FE 节点配置
添 doris fe 节点之后,还需要监控这些后端节点。对于后端多个 FE 高可用负载均衡环
境来说,这是必须的,因为 ProxySQL 需要通过每个节点的 read_only 值来自动调整它们是属于读组还是写组。
首先在后端 master 主数据节点上创建一个用于监控的用户名。

在 doris fe master 主数据库节点行执行:
#mysql -h hadoop1 -P 9030 -u root -p 
create user monitor@'192.168.8.%' identified by 'monitor';
grant ADMIN_PRIV on *.* to monitor@'192.168.8.%';
然后回到 mysql-proxy 代理层节点上配置监控
#mysql -uadmin -padmin -P6032 -h127.0.0.1
set mysql-monitor_username='monitor';
set mysql-monitor_password='monitor';
修改后,加载到 RUNTIME,并保存到 disk
load mysql variables to runtime;
save mysql variables to disk;

验证监控结果:ProxySQL 监控模块的指标都保存在 monitor 库的 log 表中。
以下是连接是否正常的监控(connect 指标的监控):
注意:可能会有很多 connect_error,这是因为没有配置监控信息时的错误,配置后如果
connect_error 的结果为 NULL 则表示正常。

select * from mysql_server_connect_log;
查看心跳信息的监控(对 ping 指标的监控)
select * from mysql_server_ping_log;
查看 read_only 日志此时也为空(正常来说,新环境配置时,这个只读日志是为空的)
select * from mysql_server_read_only_log;

load mysql servers to runtime;
save mysql servers to disk;

查看结果
select hostgroup_id,hostname,port,status,weight from mysql_servers;

(5)配置 Doris 用户
上面的所有配置都是关于后端 Doris FE 节点的,现在可以配置关于 SQL 语句的,包括:
发送 SQL 语句的用户、SQL 语句的路由规则、SQL 查询的缓存、SQL 语句的重写等等。
本小节是 SQL 请求所使用的用户配置,例如 root 用户。这要求我们需要先在后端 Doris
FE 节点添加好相关用户。这里以 root 和 doris 两个用户名为例。

首先,在 Doris FE master 主数据库节点上执行:
#mysql -h hadoop1 -P 9030 -u root -p
root 用户已经存在,直接创建 doris 用户:
create user doris@'%' identified by 'doris';
grant ADMIN_PRIV on *.* to doris@'%';
回到 mysql-proxy 代理层节点,配置 mysql_users 表,将刚才的两个用户添加到该表
中。
insert into mysql_users(username,password,default_hostgroup) 
values('root','000000',10);
insert into mysql_users(username,password,default_hostgroup) 
values('doris','doris',10);
加载用户到运行环境中,并将用户信息保存到磁盘
load mysql users to runtime;
save mysql users to disk;
 
select * from mysql_users\G
只有 active=1 的用户才是有效的用户。确保 transaction_persistent 为 1update mysql_users set transaction_persistent=1 where 
username='root';
update mysql_users set transaction_persistent=1 where 
username='doris';
load mysql users to runtime;
save mysql users to disk;
这里不需要读写分离,将这两个参数设为 trueUPDATE global_variables SET variable_value='true' WHERE 
variable_name='mysql-forward_autocommit';
UPDATE global_variables SET variable_value='true' WHERE 
variable_name='mysql-autocommit_false_is_transaction';
LOAD MYSQL VARIABLES TO RUNTIME;
SAVE MYSQL VARIABLES TO DISK;

这样就可以通过 sql 客户端,使用 doris 的用户名密码去连接了 ProxySQL 了
(6)通过 ProxySQL 连接 Doris 进行测试
分别使用 root 用户和 doris 用户测试下它们是否能路由到默认的 hostgroup_id=10
(它是一个写组)读数据。下面是通过转发端口 6033 连接的,连接的是转发到后端真正的数据库。

mysql -udoris -pdoris -P6033 -h hadoop1 -e "show databases;"

到此就结束了,可以用 MySQL 客户端,JDBC 等任何连接 MySQL 的方式连接 ProxySQL 去操作 doris 了。
(7)验证:将 hadoop1 的 fe 停止,再执行

mysql -udoris -pdoris -P6033 -h hadoop1 -e "show databases;"

能够正常使用。

2、简单查询

1)简单查询

SELECT * FROM example_site_visit LIMIT 3;
SELECT * FROM example_site_visit ORDER BY user_id;

2)Join

SELECT SUM(example_site_visit.cost) FROM example_site_visit
JOIN example_site_visit2
WHERE example_site_visit.user_id = example_site_visit2.user_id;
select 
example_site_visit.user_id,
sum(example_site_visit.cost)
from example_site_visit join example_site_visit2
where example_site_visit.user_id = example_site_visit2.user_id
group by example_site_visit.user_id;

3)子查询

SELECT SUM(cost) FROM example_site_visit2 WHERE user_id IN (SELECT 
user_id FROM example_site_visit WHERE user_id > 10003);

3、Join查询

3.1 Broadcast Join

系统默认实现 Join 的方式,是将小表进行条件过滤后,将其广播到大表所在的各个节
点上,形成一个内存 Hash 表,然后流式读出大表的数据进行 Hash Join。

Doris 会自动尝试进行 Broadcast Join,如果预估小表过大则会自动切换至 Shuffle Join。
注意,如果此时显式指定了 Broadcast Join 也会自动切换至 Shuffle Join。
1)默认使用 Broadcast Join:

EXPLAIN SELECT SUM(example_site_visit.cost) 
FROM example_site_visit
JOIN example_site_visit2
WHERE example_site_visit.city = example_site_visit2.city;

2)显式使用 Broadcast Join:

EXPLAIN SELECT SUM(example_site_visit.cost) 
FROM example_site_visit
JOIN [broadcast] example_site_visit2
WHERE example_site_visit.city = example_site_visit2.city;

3.2 Shuffle Join(Partitioned Join)

如果当小表过滤后的数据量无法放入内存的话,此时 Join 将无法完成,通常的报错应
该是首先造成内存超限。可以显式指定 Shuffle Join,也被称作 Partitioned Join。即将小表和大表都按照 Join 的 key 进行 Hash,然后进行分布式的 Join。这个对内存的消耗就会分摊到集群的所有计算节点上。

SELECT SUM(example_site_visit.cost) 
FROM example_site_visit
JOIN [shuffle] example_site_visit2
WHERE example_site_visit.city = example_site_visit2.city;

3.3 Colocation Join

Colocation Join 是在 Doris0.9 版本引入的功能,旨在为 Join 查询提供本性优化,来减少
数据在节点上的传输耗时,加速查询。

3.3.1 原理

Colocation Join 功能,是将一组拥有 CGS 的表组成一个 CG。保证这些表对应的数据分
片会落在同一个 be 节点上,那么使得两表再进行 join 的时候,可以通过本地数据进行直接join,减少数据在节点之间的网络传输时间。

➢ Colocation Group(CG):一个 CG 中会包含一张及以上的 Table。在同一个 Group
内的 Table 有着相同的 Colocation Group Schema,并且有着相同的数据分片分布。
➢ Colocation Group Schema(CGS):用于描述一个 CG 中的 Table,和 Colocation
相关的通用 Schema 信息。包括分桶列类型,分桶数以及副本数等。

一个表的数据,最终会根据分桶列值 Hash、对桶数取模的后落在某一个分桶内。假设
一个 Table 的分桶数为 8,则共有 [0, 1, 2, 3, 4, 5, 6, 7] 8 个分桶(Bucket),我们称这样一个序列为一个 BucketsSequence。每个 Bucket 内会有一个或多个数据分片(Tablet)。当表为单分区表时,一个 Bucket 内仅有一个 Tablet。如果是多分区表,则会有多个。

使用限制:
(1)建表时两张表的分桶列的类型和数量需要完全一致,并且桶数一致,才能保证多
张表的数据分片能够一一对应的进行分布控制。
(2)同一个 CG 内所有表的所有分区(Partition)的副本数必须一致。如果不一致,
可能出现某一个 Tablet 的某一个副本,在同一个 BE 上没有其他的表分片的副本对应。
(3)同一个 CG 内的表,分区的个数、范围以及分区列的类型不要求一致。

3.3.2 使用

1)建两张表,分桶列都为 int 类型,且桶的个数都是 8 个。副本数都为默认副本数。

CREATE TABLE `tbl1` (
 `k1` date NOT NULL COMMENT "",
 `k2` int(11) NOT NULL COMMENT "",
 `v1` int(11) SUM NOT NULL COMMENT ""
) ENGINE=OLAP
AGGREGATE KEY(`k1`, `k2`)
PARTITION BY RANGE(`k1`)
(
 PARTITION p1 VALUES LESS THAN ('2019-05-31'),
 PARTITION p2 VALUES LESS THAN ('2019-06-30')
)
DISTRIBUTED BY HASH(`k2`) BUCKETS 8
PROPERTIES (
 "colocate_with" = "group1"
);
CREATE TABLE `tbl2` (
 `k1` datetime NOT NULL COMMENT "",
 `k2` int(11) NOT NULL COMMENT "",
 `v1` double SUM NOT NULL COMMENT ""
) ENGINE=OLAP
AGGREGATE KEY(`k1`, `k2`)
DISTRIBUTED BY HASH(`k2`) BUCKETS 8
PROPERTIES (
 "colocate_with" = "group1"
);

2)编写查询语句,并查看执行计划

explain SELECT * FROM tbl1 INNER JOIN tbl2 ON (tbl1.k2 = tbl2.k2);

HASH JOIN 处 colocate 显示为 true,代表优化成功。
3)查看 Group

SHOW PROC '/colocation_group';

当 Group 中最后一张表彻底删除后(彻底删除是指从回收站中删除。通常,一张表通过
DROP TABLE 命令删除后,会在回收站默认停留一天的时间后,再删除),该 Group 也会被自动删除。
4)修改表 Colocate Group 属性

ALTER TABLE tbl SET ("colocate_with" = "group2");

如果该表之前没有指定过 Group,则该命令检查 Schema,并将该表加入到该 Group
(Group 不存在则会创建)。
如果该表之前有指定其他 Group,则该命令会先将该表从原有 Group 中移除,并加入新
Group(Group 不存在则会创建)。

5)删除表的 Colocation 属性

ALTER TABLE tbl SET ("colocate_with" = "");

6)其他操作
当对一个具有 Colocation 属性的表进行增加分区(ADD PARTITION)、修改副本数时,
Doris 会检查修改是否会违反 Colocation Group Schema,如果违反则会拒绝。

3.4 Bucket Shuffle Join

Bucket Shuffle Join 是在 Doris 0.14 版本中正式加入的新功能。旨在为某些 Join 查询提
供本地性优化,来减少数据在节点间的传输耗时,来加速查询。

3.4.1 原理

Doris 支持的常规分布式 Join 方式包括了 shuffle join 和 broadcast join。这两种 join 都会
导致不小的网络开销:
举个例子,当前存在 A 表与 B 表的 Join 查询,它的 Join 方式为 HashJoin,不同 Join 类型的开销如下:
⚫ Broadcast Join: 如果根据数据分布,查询规划出 A 表有 3 个执行的 HashJoinNode,
那么需要将 B 表全量的发送到 3 个 HashJoinNode,那么它的网络开销是 3B,它的
内存开销也是 3B。
⚫ Shuffle Join: Shuffle Join 会将 A,B 两张表的数据根据哈希计算分散到集群的节点
之中,所以它的网络开销为 A + B,内存开销为 B。

在 FE 之中保存了 Doris 每个表的数据分布信息,如果 join 语句命中了表的数据分布列,
使用数据分布信息来减少 join 语句的网络与内存开销,这就是 Bucket Shuffle Join,原理如下图:

在这里插入图片描述
SQL 语句为 A 表 join B 表,并且 join 的等值表达式命中了 A 的数据分布列。而 Bucket
Shuffle Join 会根据 A 表的数据分布信息,将 B 表的数据发送到对应的 A 表的数据存储计算节点。Bucket Shuffle Join 开销如下:
⚫ 网络开销: B < min(3B, A + B)
⚫ 内存开销: B <= min(3B, B)

可见,相比于 Broadcast Join 与 Shuffle Join, Bucket Shuffle Join 有着较为明显的性能
优势。减少数据在节点间的传输耗时和 Join 时的内存开销。相对于 Doris 原有的 Join 方式,它有着下面的优点:
⚫ 首先,Bucket-Shuffle-Join 降低了网络与内存开销,使一些 Join 查询具有了更好的
性能。尤其是当 FE 能够执行左表的分区裁剪与桶裁剪时。
⚫ 其次,同时与 Colocate Join 不同,它对于表的数据分布方式并没有侵入性,这对于
用户来说是透明的。对于表的数据分布没有强制性的要求,不容易导致数据倾斜的
问题。
⚫ 最后,它可以为 Join Reorder 提供更多可能的优化空间。

3.4.2 使用

1)设置 Session 变量,从 0.14 版本开始默认为 true

show variables like '%bucket_shuffle_join%';
set enable_bucket_shuffle_join = true;

在 FE 进行分布式查询规划时,优先选择的顺序为 Colocate Join -> Bucket Shuffle Join ->Broadcast Join -> Shuffle Join。但是如果用户显式 hint 了 Join 的类型,如:

select * from test join [shuffle] baseall on test.k1 = baseall.k1;

则上述的选择优先顺序则不生效。

2)通过 explain 查看 join 类型

EXPLAIN SELECT SUM(example_site_visit.cost) 
FROM example_site_visit
JOIN example_site_visit2
ON example_site_visit.user_id = example_site_visit2.user_id;

在 Join 类型之中会指明使用的 Join 方式为:BUCKET_SHUFFLE。

3.4.3 注意事项

(1)Bucket Shuffle Join 只生效于 Join 条件为等值的场景,原因与 Colocate Join 类似,它们都依赖 hash 来计算确定的数据分布。

(2)在等值 Join 条件之中包含两张表的分桶列,当左表的分桶列为等值的 Join 条件
时,它有很大概率会被规划为 Bucket Shuffle Join。

(3)由于不同的数据类型的 hash 值计算结果不同,所以 Bucket Shuffle Join 要求左表
的分桶列的类型与右表等值 join 列的类型需要保持一致,否则无法进行对应的规划。

(4)Bucket Shuffle Join 只作用于 Doris 原生的 OLAP 表,对于 ODBC,MySQL,ES 等外表,当其作为左表时是无法规划生效的。

(5)对于分区表,由于每一个分区的数据分布规则可能不同,所以 Bucket Shuffle Join
只能保证左表为单分区时生效。所以在 SQL 执行之中,需要尽量使用 where 条件使分区裁剪的策略能够生效。

(6)假如左表为 Colocate 的表,那么它每个分区的数据分布规则是确定的,Bucket
Shuffle Join 能在 Colocate 表上表现更好。

3.5 Runtime Filter

Runtime Filter 是在 Doris 0.15 版本中正式加入的新功能。旨在为某些 Join 查询在运
行时动态生成过滤条件,来减少扫描的数据量,避免不必要的 I/O 和网络传输,从而加速查询。

3.5.1 原理

Runtime Filter 在查询规划时生成,在 HashJoinNode 中构建,在 ScanNode 中应用。
举个例子,当前存在 T1 表与 T2 表的 Join 查询,它的 Join 方式为 HashJoin,T1 是一张事实表,数据行数为 100000,T2 是一张维度表,数据行数为 2000,Doris join 的实际情况是:
在这里插入图片描述
显而易见对 T2 扫描数据要远远快于 T1,如果我们主动等待一段时间再扫描 T1,等 T2
将扫描的数据记录交给 HashJoinNode 后,HashJoinNode 根据 T2 的数据计算出一个过滤条件,比如 T2 数据的最大和最小值,或者构建一个 Bloom Filter,接着将这个过滤条件发给等待扫描 T1 的 ScanNode,后者应用这个过滤条件,将过滤后的数据交给 HashJoinNode,从而减少 probe hash table 的次数和网络开销,这个过滤条件就是 Runtime Filter,效果如下:
在这里插入图片描述
如果能将过滤条件(Runtime Filter)下推到存储引擎,则某些情况下可以利用索引来直
接减少扫描的数据量,从而大大减少扫描耗时,效果如下:
在这里插入图片描述
可见,和谓词下推、分区裁剪不同,Runtime Filter 是在运行时动态生成的过滤条件,即
在查询运行时解析 join on clause 确定过滤表达式,并将表达式广播给正在读取左表的
ScanNode,从而减少扫描的数据量,进而减少 probe hash table 的次数,避免不必要的 I/O 和网络传输。
Runtime Filter 主要用于优化针对大表的 join,如果左表的数据量太小,或者右表的数据
量太大,则 Runtime Filter 可能不会取得预期效果。

3.5.2 使用

1)指定 RuntimeFilter 类型

set runtime_filter_type="BLOOM_FILTER,IN,MIN_MAX";

2)建表

CREATE TABLE test (t1 INT) DISTRIBUTED BY HASH (t1) BUCKETS 2 
PROPERTIES("replication_num" = "1");
INSERT INTO test VALUES (1), (2), (3), (4);
CREATE TABLE test2 (t2 INT) DISTRIBUTED BY HASH (t2) BUCKETS 2 
PROPERTIES("replication_num" = "1");
INSERT INTO test2 VALUES (3), (4), (5);

3)查看执行计划

EXPLAIN SELECT t1 FROM test JOIN test2 where test.t1 = test2.t2;

可以看到:
HASH JOIN生成了 ID 为 RF000 的 IN predicate,其中test2.t2的 key values 仅在运行 时可知,在 OlapScanNode 使用了该 IN predicate 用于在读取test.t1`时过滤不必要的数据。

4)通过 profile 查看效果

set enable_profile=true;
SELECT t1 FROM test JOIN test2 where test.t1 = test2.t2;

查看对应 fe 节点的 webui,可以查看查询内部工作的详细信息:
http://hadoop1:8030/QueryProfile/
(1)可以看到每个 Runtime Filter 是否下推、等待耗时、以及 OLAP_SCAN_NODE 从
prepare 到接收到 Runtime Filter 的总时长。

RuntimeFilter:in:
 - HasPushDownToEngine: true
 - AWaitTimeCost: 0ns
 - EffectTimeCost: 2.76ms

(2)在 profile 的 OLAP_SCAN_NODE 中可以查看 Runtime Filter 下推后的过滤效果和
耗时。

 - RowsVectorPredFiltered: 9.320008M (9320008)
 - VectorPredEvalTime: 364.39ms

3.5.3 具体参数说明

1) 大多数情况下,只需要调整 runtime_filter_type 选项,其他选项保持默认即可:
包括 BLOOM_FILTER、IN、MIN_MAX(也可以通过数字设置),默认会使用 IN,部
分情况下同时使用 Bloom Filter、MinMax Filter、IN predicate 时性能更高,每个类型含义如下:

(1)Bloom Filter: 有一定的误判率,导致过滤的数据比预期少一点,但不会导致最终
结果不准确,在大部分情况下 Bloom Filter 都可以提升性能或对性能没有显著影响,但在部分情况下会导致性能降低。
① Bloom Filter 构建和应用的开销较高,所以当过滤率较低时,或者左表数据量较
少时,Bloom Filter 可能会导致性能降低。
② 目前只有左表的 Key 列应用 Bloom Filter 才能下推到存储引擎,而测试结果显
示 Bloom Filter 不下推到存储引擎时往往会导致性能降低。
③ 目前 Bloom Filter 仅在 ScanNode 上使用表达式过滤时有短路(short-circuit)逻辑,
即当假阳性率(实际是假但误辨为真的情况)过高时,不继续使用 Bloom Filter,但当
Bloom Filter 下推到存储引擎后没有短路逻辑,所以当过滤率较低时可能导致性能降低。

(2)MinMax Filter: 包含最大值和最小值,从而过滤小于最小值和大于最大值的数据,
MinMax Filter 的过滤效果与 join on clause 中 Key 列的类型和左右表数据分布有关。
① 当 join on clause 中 Key 列的类型为 int/bigint/double 等时,极端情况下,如果左
右表的最大最小值相同则没有效果,反之右表最大值小于左表最小值,或右表最小值大
于左表最大值,则效果最好。
② 当 join on clause 中 Key 列的类型为 varchar 等时,应用 MinMax Filter 往往会导
致性能降低。

(3)IN predicate: 根据 join on clause 中 Key 列在右表上的所有值构建 IN predicate,使用构建的 IN predicate 在左表上过滤,相比 Bloom Filter 构建和应用的开销更低,在右表数据量较少时往往性能更高。
① 默认只有右表数据行数少于 1024 才会下推(可通过 session 变量中的
runtime_filter_max_in_num 调整)。
② 目前 IN predicate 已实现合并方法。
③ 当同时指定 In predicate 和其他 filter ,并且 in 的 过 滤 数 值 没 达 到runtime_filter_max_in_num 时,会尝试把其他 filter 去除掉。原因是 In predicate 是精确
的过滤条件,即使没有其他 filter 也可以高效过滤,如果同时使用则其他 filter 会做无用功。目前仅在 Runtime filter 的生产者和消费者处于同一个 fragment 时才会有去除非 in
filter 的逻辑。

2)其他查询选项通常仅在某些特定场景下,才需进一步调整以达到最优效果。通常只在性能测试后,针对资源密集型、运行耗时足够长且频率足够高的查询进行优化。
➢ runtime_filter_mode: 用于调整 Runtime Filter 的下推策略,包括 OFF、LOCAL、GLOBAL三种策略,默认设置为 GLOBAL 策略
➢ runtime_filter_wait_time_ms: 左表的 ScanNode 等待每个 Runtime Filter 的时间,默认1000ms
➢ runtime_filters_max_num: 每个查询可应用的 Runtime Filter 中 Bloom Filter 的最大数量,默认 10
➢ runtime_bloom_filter_min_size: Runtime Filter 中 Bloom Filter 的最小长度,默认 1048576(1M)
➢ runtime_bloom_filter_max_size: Runtime Filter 中 Bloom Filter 的最大长度,默认 16777216(16M)
➢ runtime_bloom_filter_size: Runtime Filter中Bloom Filter的默认长度,默认2097152(2M)
➢ runtime_filter_max_in_num: 如果 join 右表数据行数大于这个值,我们将不生成 IN
predicate,默认 1024

3.5.4 注意事项

(1)只支持对 join on clause 中的等值条件生成 Runtime Filter,不包括 Null-safe 条件,因为其可能会过滤掉 join 左表的 null 值。
(2)不支持将 Runtime Filter 下推到 left outer、full outer、anti join 的左表;
(3)不支持 src expr 或 target expr 是常量;
(4)不支持 src expr 和 target expr 相等;
(5)不支持 src expr 的类型等于 HLL 或者 BITMAP;
(6)目前仅支持将 Runtime Filter 下推给 OlapScanNode;
(7)不支持 target expr 包含 NULL-checking 表达式,比如 COALESCE/IFNULL/CASE,因为当 outer join 上层其他 join 的 join on clause 包含 NULL-checking 表达式并生成 Runtime Filter 时,将这个 Runtime Filter 下推到 outer join 的左表时可能导致结果不正确;
(8)不支持 target expr 中的列(slot)无法在原始表中找到某个等价列;
(9)不支持列传导,这包含两种情况:
(10)一是例如 join on clause 包含 A.k = B.k and B.k = C.k 时,目前 C.k 只可以下推给
B.k,而不可以下推给 A.k;
(11)二是例如 join on clause 包含 A.a + B.b = C.c,如果 A.a 可以列传导到 B.a,即 A.a和 B.a 是等价的列,那么可以用 B.a 替换 A.a,然后可以尝试将 Runtime Filter 下推给 B(如果 A.a 和 B.a 不是等价列,则不能下推给 B,因为 target expr 必须与唯一一个 join 左表绑定);
(12)Target expr 和 src expr 的类型必须相等,因为 Bloom Filter 基于 hash,若类型不
等则会尝试将 target expr 的类型转换为 src expr 的类型;
(13)不支持 PlanNode.Conjuncts 生成的 Runtime Filter 下推,与 HashJoinNode 的
eqJoinConjuncts 和 otherJoinConjuncts 不同,PlanNode.Conjuncts 生成的 Runtime Filter 在测试中发现可能会导致错误的结果,例如 IN 子查询转换为 join 时,自动生成的 join on clause将保存在 PlanNode.Conjuncts 中,此时应用 Runtime Filter 可能会导致结果缺少一些行。

4、SQL函数

1)查看函数名:

show builtin functions in test_db;

2)查看函数具体信息,比如查看 year 函数具体信息

show full builtin functions in test_db like 'year';

3)官网
https://doris.apache.org/zh-CN/sql-reference/sql-functions/date-time-functions/convert_tz.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Doris-查询(三) 的相关文章

  • 【计算机毕业设计】北关村基本办公管理系统

    在如今社会上 关于信息上面的处理 没有任何一个企业或者个人会忽视 如何让信息急速传递 并且归档储存查询 采用之前的纸张记录模式已经不符合当前使用要求了 所以 对北关村基本办公信息管理的提升 也为了对北关村基本办公信息进行更好的维护 北关村基
  • Web 安全漏洞之 OS 命令注入

    什么是 OS 命令注入 上周我们分享了一篇 Web 安全漏洞之 SQL 注入 其原理简单来说就是因为 SQL 是一种结构化字符串语言 攻击者利用可以随意构造语句的漏洞构造了开发者意料之外的语句 而今天要讲的 OS 命令注入其实原理和 SQL
  • 白帽子如何快速挖到人生的第一个漏洞 | 购物站点挖掘商城漏洞

    本文针对人群 很多朋友们接触安全都是通过书籍 网上流传的PDF 亦或是通过论坛里的文章 但可能经过了这样一段时间的学习 了解了一些常见漏洞的原理之后 对于漏洞挖掘还不是很清楚 甚至不明白如何下手 可能你通过 sql labs 初步掌握了sq
  • messages,CentOS 7不收集日志或不存在 /var/log/messages

    var log message var log secure等都不记录了 并且都是空文件 重启机器 reboot 无效 重启日志 systemctl start rsyslog 无效 怀疑空间不足 删除 var log messages 重
  • Python爬虫实战:IP代理池助你突破限制,高效采集数据

    当今互联网环境中 为了应对反爬虫 匿名访问或绕过某些地域限制等需求 IP代理池成为了一种常用的解决方案 IP代理池是一个包含多个可用代理IP地址的集合 可以通过该代理池随机选择可用IP地址来进行网络请求 IP代理池是一组可用的代理IP地址
  • Jmeter 性能-并发量计算

    并发概念 指网站在同一时间访问的人数 人数越大瞬间带宽要求更高 服务器并发量分为 业务并发用户数 最大并发访问数 系统用户数 同时在线用户数 估算业务并发量的公式 C nL T C C 3 C的平方根 说明 C是平均的业务并发用户数 n是l
  • python超详细基础文件操作【建议收藏】

    文章目录 前言 发现宝藏 1 文件操作 1 1 文件打开与关闭 1 1 1 打开文件 1 1 2 关闭文件 1 2 访问模式及说明 2 文件读写 2 1 写数据 write 2 2 读数据 read 2 3 读数据 readlines 2
  • 如何使用Imagewheel搭建一个简单的的私人图床无公网ip也能访问

    文章目录 1 前言 2 Imagewheel网站搭建 2 1 Imagewheel下载和安装 2 2 Imagewheel网页测试 2 3 cpolar的安装和注册 3 本地网页发布 3 1 Cpolar临时数据隧道
  • 基于java的学生宿舍管理系统设计与实现

    基于java的学生宿舍管理系统设计与实现 I 引言 A 研究背景和动机 基于Java的学生宿舍管理系统设计与实现的研究背景和动机 在数字化时代的推动下 学生宿舍管理系统已经成为了管理学生宿舍的重要工具 学生宿舍管理系统能够帮助管理者更好地管
  • 深入了解 Python MongoDB 操作:排序、删除、更新、结果限制全面解析

    Python MongoDB 排序 对结果进行排序 使用 sort 方法对结果进行升序或降序排序 sort 方法接受一个参数用于 字段名 一个参数用于 方向 升序是默认方向 示例 按名称按字母顺序对结果进行排序 import pymongo
  • 【计算机毕业设计】电商个性化推荐系统

    伴随着我国社会的发展 人民生活质量日益提高 于是对电商个性化推荐进行规范而严格是十分有必要的 所以许许多多的信息管理系统应运而生 此时单靠人力应对这些事务就显得有些力不从心了 所以本论文将设计一套电商个性化推荐系统 帮助商家进行商品信息 在
  • 【计算机毕业设计】趵突泉景区的智慧导游小程序_5ztvv

    当今社会已经步入了科学技术进步和经济社会快速发展的新时期 国际信息和学术交流也不断加强 计算机技术对经济社会发展和人民生活改善的影响也日益突出 人类的生存和思考方式也产生了变化 传统趵突泉景区的智慧导游采取了人工的管理方法 但这种管理方法存
  • 【计算机毕业设计】白优校园社团网站的设计与实现

    近些年 随着中国经济发展 人民的生活质量逐渐提高 对网络的依赖性越来越高 通过网络处理的事务越来越多 随着白优校园社团网站的常态化 如果依然采用传统的管理方式 将会为工作人员带来庞大的工作量 这将是一个巨大考验 需要投入大量人力开展对社团
  • 【计算机毕业设计】OA公文发文管理系统_xtv98

    近年来 人们的生活方式以网络为主题不断进化 OA公文发文管理就是其中的一部分 现在 无论是大型的还是小型的网站 都随处可见 不知不觉中已经成为我们生活中不可或缺的存在 随着社会的发展 除了对系统的需求外 我们还要促进经济发展 提高工作效率
  • 一台java服务器可以跑多少个线程?

    一台java服务器可以跑多少个线程 一台java服务器能跑多少个线程 这个问题来自一次线上报警如下图 超过了我们的配置阈值 打出jstack文件 通过IBM Thread and Monitor Dump Analyzer for Java
  • Redis分布式锁--java实现

    文章目录 Redis分布式锁 方案 SETNX EXPIRE 基本原理 比较好的实现 会产生四个问题 几种解决原子性的方案
  • 30天精通Nodejs--第二十天:express-操作mysql

    目录 前言 安装依赖并配置MySQL连接 安装mysql2库 配置连接信息 在Express应用中使用MySQL 结合Express路由实现CRUD操作 整合到主应用 结语 前言 在Node js中使用Expre
  • 服务器VPS是什么意思?一文了解其含义与重要性

    在今天的数字时代 服务器扮演着至关重要的角色 它们是网站 应用程序和在线业务的基石 但是 你是否听说过VPS 本文将深入探讨什么是服务器VPS 以及为什么它在今天的互联网世界中如此重要 什么是服务器VPS 服务器的基本概念 在我们深入探讨V
  • 温室气体排放更敏感的模型(即更高的平衡气候敏感性(ECS))在数年到数十年时间尺度上也具有更高的温度变化(Python代码实现)

    欢迎来到本博客 博主优势 博客内容尽量做到思维缜密 逻辑清晰 为了方便读者 座右铭 行百里者 半于九十 本文目录如下 目录 1 概述 2 运行结果 3 参考文献 4 Python代码 数据
  • SAP ERP系统是什么?SAP好用吗?

    A公司是一家传统制造企业 公司曾先后使用过数个管理软件系统 但各部门使用的软件都是单独功能 导致企业日常管理中数据流与信息流相对独立 形成了 信息孤岛 随着公司近年业务规模的快速发展以及客户数量的迅速增加 企业原有的信息系统在销售预测及生产

随机推荐

  • hlog 详解

    为了防止regionserver 宕机时 正在写数据 没写完 然后 wal预先写入磁盘完成 由于wal没有回滚机制 故写盘速度快 StoreFile在写盘时有回滚机制 效率较慢 同时 如果hlog写盘失败 则认为写数据操作失败 需要重新发起
  • 产品经理 研发管理 ——周辉

    产品经理 研发管理 周辉 1 产品运作的四大体系 1 1 1 欠缺的市场体系和产品开发体系 1 1 2 技术开发与产品开发的区别
  • 使用Python和OpenCV标记超级像素的炫彩度

    使用Python和OpenCV标记超级像素的炫彩度 1 效果图 2 步骤 3 源代码 参考 这篇博客将介绍如何使用SLIC分割算法来计算输入图像的超像素 并对每一块超像素区域计算炫彩度量值 然后将每个区域的炫彩度量值加入到掩模图像 以展示图
  • Linux系统中杀死僵尸进程的方法

    在linux系统管理中 当用ps命令观察进程的执行状态时 经常看到某些进程的状态栏为defunct 这就是所谓的 僵尸 进程 僵尸 进程是一个早已 死亡的进程 但在进程表 processs table 中仍占了一个位置 slot 由于进程表
  • qt通过ODBC驱动与mysql连接

    参考 https blog csdn net m0 38128647 article details 89482413 创建你的mysql服务器 我创建的mysql服务名称为mysql80 新建一个test数据库 里面新建一张student
  • 关于 Linux 之父,你可能不知道的 7 件事

    如果让你现在说出三个程序员的名字 Linus 很可能就在其中 作为世界上最著名的电脑程序员 黑客之一 Linus Benedict Torvalds 写出了 Linux 内核 1 0 版 发起了开源运动 开发了代码管理工具 Git 这三个成
  • Vue3封装全局函数式组件

    文章目录 前言 一 函数式组件是什么 二 创建一个函数式组件 1 封装toast组件 2 创建应用实例 3 注册插件 可省略 Q A 补充一些注释 为什么采用调用函数方法的方式去控制显隐 函数式组件的这两个文件之间的联系 三 调用 1 注册
  • 服务器记录到虚拟mac,Mac 模拟JSON数据

    一 使用Apache本地服务器 1 开启 sudo usr sbin apachectl start 在浏览器中输入 https localhost 页面显示 it works 2 其实本地apachec指向一个文件下 Library We
  • Mycat/Mysql主从复制搭建详解

    Mycat server 1 6 mysql 5 7 24 linux 工具下载地址 mycat mysql navivat 链接 https pan baidu com s 1KCmSgXYXs9O5vHMHIgnbAg 提取码 ukaq
  • java 操作ES 增删改查总结

    本实例框架采用 nutz ES 如果 您查找相关知识 请注意过滤不相干的信息 controller 层 package com test ownasset controller import java io File import java
  • centOS 6 服务管理与服务脚本

    服务管理与服务脚本 linux服务 服务管理与服务脚本 linux服务 服务启动过程详解 chkconfig命令 非独立服务与xinetd进程 一个特殊的服务脚本 服务启动过程详解 在开机启动过程中 我们计算机的各种服务也会按照配置信息启动
  • python 数据标准化

    def datastandard from sklearn import preprocessing import numpy as np x np array 1 1 2 2 0 0 0 1 1 print 原始数据为 n x print
  • 交换机上抓包

    1 常用交换机抓包方式 华为 华三 锐捷交换机一般使用packet capture命令可以进行抓包 Arista交换机通过在bash下 使用linux命令tcpdump进行抓包 Cisco nexus 抓包使用ethanalyze命令 具体
  • AS400银行核心系统开发中的技术总结--数据字典和枚举值

    数据字典和枚举值 在核心系统应用开发中 数据字典有举足轻重的作用 数据字典是对系统中所有字段的归纳抽象 需要规范同类字段的类型长度 方便定义和修改 但是 在过去的核心系统中 数据字典的理解往往也会有失误 常见的错误方法 是试图穷举定义所有可
  • Flink Client 使用技巧和心得(Flink on Zeppelin)

    Flink 链接Kafka 先建立catalog CREATE CATALOG flink hive WITH type hive default database imods hive conf dir home admin flink
  • 八个维度讲解秒杀系统架构分析与实战

    路人 Java充电社 2022 09 06 08 06 发表于上海 收录于合集 java充电社263个 大家好 我是路人 更多优质文章见个人博客 http itsoku com Java充电社 Java充电社 专注分享Java技术干货 包括
  • 最小熵原理

    种草很好的博文 苏剑林 2018 Apr 18 最小熵原理 一 无监督学习的原理 Blog post Retrieved from https spaces ac cn archives 5448 苏剑林 2018 Apr 24 最小熵原理
  • scrapy框架的使用

    1 什么是scrapy框架 文档地址 http scrapy chs readthedocs io zh CN 1 0 intro overview html 这个详细的文档地址 大家可以保存一下 之前的文章中也有一些链接大家可以保存下来方
  • 云计算中的存储基础知识

    物理存储方式 云计算中的三辆马车 计算 网络 存储 硬盘分为两种型态 机械硬盘 HDD 和固态硬盘 SSD 物理磁盘类型 SATA盘 串口硬盘 常用于个人电脑 物理磁盘类型 SAS盘 常用于服务器 物理磁盘类型 NL SAS盘 采用SAS磁
  • Doris-查询(三)

    目录 1 查询设置 1 1 增大内存 1 2 修改超时时间 1 3 查询重试和高可用 1 3 1 代码方式 1 3 2 JDBC Connector 1 3 3 ProxySQL 方式 2 简单查询 3 Join查询 3 1 Broadca