Apache Doris 入门教程04:连接方式与使用指南

使用指南

Doris 采用 MySQL 协议进行通信,用户可通过 MySQL client 或者 MySQL JDBC连接到 Doris 集群。选择 MySQL client 版本时建议采用5.1 之后的版本,因为 5.1 之前不能支持长度超过 16 个字符的用户名。本文以 MySQL client 为例,通过一个完整的流程向用户展示 Doris 的基本使用方法。

创建用户​

下载免安装的 MySQL 客户端。

Root用户登录与密码修改​

Doris 内置 root,密码默认为空。

备注:

Doris 提供的默认 root

root 用户默认拥有集群所有权限。同时拥有 Grant_priv 和 Node_priv 的用户,可以将该权限赋予其他用户,拥有节点变更权限,包括 FE、BE、BROKER 节点的添加、删除、下线等操作。

启动完 Doris 程序之后,可以通过 root 或 admin 用户连接到 Doris 集群。 使用下面命令即可登录 Doris,登录后进入到Doris对应的Mysql命令行操作界面:

[root@doris ~]# mysql  -h FE_HOST -P9030 -uroot
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 41
Server version: 5.1.0 Doris version 1.0.0-preview2-b48ee2734

Copyright (c) 2000, 2022, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> 

FE_HOST 是任一FE节点的IP地址,9030 是fe.conf 中的 query_port 配置;

登录后,可以通过以下命令修改root密码:

mysql> SET PASSWORD FOR 'root' = PASSWORD('your_password');
Query OK, 0 rows affected (0.00 sec)

your_password是为root用户设置的新密码,可以随意设置,建议设置为强密码增加安全性,下次登录就用新密码登录。

创建新用户​

我们可以通过下面的命令创建一个普通用户test

mysql> CREATE USER 'test' IDENTIFIED BY 'test_passwd';
Query OK, 0 rows affected (0.00 sec)

后续登录时就可以通过下面链接命令登录:

[root@doris ~]# mysql -h FE_HOST -P9030 -utest -ptest_passwd

注意:新创建的普通用户默认没有任何权限,权限授予可以参考后面的权限授予。

数据表的创建与数据导入​

创建数据库​

初始可以通过 root 或 admin 用户创建数据库:

CREATE DATABASE example_db;

所有命令都可以使用 HELP command; 查看到详细的语法帮助,如:HELP CREATE DATABASE;。也可以查阅官网 SHOW CREATE DATABASE 命令手册。

如果不清楚命令的全名,可以使用 "help 命令某一字段" 进行模糊查询。如键入 'HELP CREATE',可以匹配到 CREATE DATABASECREATE TABLECREATE USER 等命令。

mysql> HELP CREATE;
Many help items for your request exist.
To make a more specific request, please type 'help ',
where  is one of the following
topics:
  CREATE CATALOG
  CREATE DATABASE
  CREATE ENCRYPTKEY
  CREATE EXTERNAL TABLE
  CREATE FILE
  CREATE FUNCTION
  CREATE INDEX
  CREATE MATERIALIZED VIEW
  CREATE POLICY
  CREATE REPOSITORY
  CREATE RESOURCE
  CREATE ROLE
  CREATE ROUTINE LOAD
  CREATE SQL BLOCK RULE
  CREATE SYNC JOB
  CREATE TABLE
  CREATE TABLE AS SELECT
  CREATE TABLE LIKE
  CREATE USER
  CREATE VIEW
  CREATE WORKLOAD GROUP
  SHOW CREATE CATALOG
  SHOW CREATE DATABASE
  SHOW CREATE FUNCTION
  SHOW CREATE LOAD
  SHOW CREATE REPOSITORY
  SHOW CREATE ROUTINE LOAD
  SHOW CREATE TABLE

数据库创建完成之后,可以通过 SHOW DATABASES 查看数据库信息。

mysql> SHOW DATABASES;
+--------------------+
| Database           |
+--------------------+
| example_db         |
| information_schema |
+--------------------+
2 rows in set (0.00 sec)

information_schema数据库是为了兼容MySQL协议而存在,实际中信息可能不是很准确,所以关于具体数据库的信息建议通过直接查询相应数据库而获得。

账户授权​

example_db 创建完成之后,可以通过 root/admin 账户使用GRANT命令将 example_db 读写权限授权给普通账户,如 test。授权之后采用 test 账户登录就可以操作 example_db 数据库了。

mysql> GRANT ALL ON example_db TO test;
Query OK, 0 rows affected (0.01 sec)

建表​

使用 CREATE TABLE 命令建立一个表(Table)。更多详细参数可以 HELP CREATE TABLE;

首先,我们需要使用USE命令来切换数据库:

mysql> USE example_db;
Database changed

Doris支持复合分区和单分区两种建表方式。下面以聚合模型为例,分别演示如何创建两种分区的数据表。

单分区​

建立一个名字为 table1 的逻辑表。分桶列为 siteid,桶数为 10。

这个表的 schema 如下:

  • siteid:类型是INT(4字节), 默认值为10
  • citycode:类型是SMALLINT(2字节)
  • username:类型是VARCHAR, 最大长度为32, 默认值为空字符串
  • pv:类型是BIGINT(8字节), 默认值是0; 这是一个指标列, Doris内部会对指标列做聚合操作, 这个列的聚合方法是求和(SUM)

建表语句如下:

CREATE TABLE table1
(
    siteid INT DEFAULT '10',
    citycode SMALLINT,
    username VARCHAR(32) DEFAULT '',
    pv BIGINT SUM DEFAULT '0'
)
AGGREGATE KEY(siteid, citycode, username)
DISTRIBUTED BY HASH(siteid) BUCKETS 10
PROPERTIES("replication_num" = "1");

多分区​

建立一个名字为 table2 的逻辑表。

这个表的 schema 如下:

  • event_day:类型是DATE,无默认值
  • siteid:类型是INT(4字节), 默认值为10
  • citycode:类型是SMALLINT(2字节)
  • username:类型是VARCHAR, 最大长度为32, 默认值为空字符串
  • pv:类型是BIGINT(8字节), 默认值是0; 这是一个指标列, Doris 内部会对指标列做聚合操作, 这个列的聚合方法是求和(SUM)

我们使用 event_day 列作为分区列,建立3个分区: p201706, p201707, p201708

  • p201706:范围为 [最小值, 2017-07-01)
  • p201707:范围为 [2017-07-01, 2017-08-01)
  • p201708:范围为 [2017-08-01, 2017-09-01)

注意区间为左闭右开。

每个分区使用 siteid 进行哈希分桶,桶数为10

建表语句如下:

CREATE TABLE table2
(
    event_day DATE,
    siteid INT DEFAULT '10',
    citycode SMALLINT,
    username VARCHAR(32) DEFAULT '',
    pv BIGINT SUM DEFAULT '0'
)
AGGREGATE KEY(event_day, siteid, citycode, username)
PARTITION BY RANGE(event_day)
(
    PARTITION p201706 VALUES LESS THAN ('2017-07-01'),
    PARTITION p201707 VALUES LESS THAN ('2017-08-01'),
    PARTITION p201708 VALUES LESS THAN ('2017-09-01')
)
DISTRIBUTED BY HASH(siteid) BUCKETS 10
PROPERTIES("replication_num" = "1");

数据表创建完成后,可以查看 example_db 中表的信息:

mysql> SHOW TABLES;
+----------------------+
| Tables_in_example_db |
+----------------------+
| table1               |
| table2               |
+----------------------+
2 rows in set (0.01 sec)

mysql> DESC table1;
+----------+-------------+------+-------+---------+-------+
| Field    | Type        | Null | Key   | Default | Extra |
+----------+-------------+------+-------+---------+-------+
| siteid   | int(11)     | Yes  | true  | 10      |       |
| citycode | smallint(6) | Yes  | true  | N/A     |       |
| username | varchar(32) | Yes  | true  |         |       |
| pv       | bigint(20)  | Yes  | false | 0       | SUM   |
+----------+-------------+------+-------+---------+-------+
4 rows in set (0.00 sec)

mysql> DESC table2;
+-----------+-------------+------+-------+---------+-------+
| Field     | Type        | Null | Key   | Default | Extra |
+-----------+-------------+------+-------+---------+-------+
| event_day | date        | Yes  | true  | N/A     |       |
| siteid    | int(11)     | Yes  | true  | 10      |       |
| citycode  | smallint(6) | Yes  | true  | N/A     |       |
| username  | varchar(32) | Yes  | true  |         |       |
| pv        | bigint(20)  | Yes  | false | 0       | SUM   |
+-----------+-------------+------+-------+---------+-------+
5 rows in set (0.00 sec)

注意事项:

  1. 上述表通过设置 replication_num 建的都是单副本的表,Doris建议用户采用默认的 3 副本设置,以保证高可用。
  2. 可以对多分区表动态的增删分区,详见 HELP ALTER TABLE; 中 Partition 相关部分。
  3. 数据导入可以导入指定的 Partition,详见 HELP LOAD;
  4. 可以动态修改表的 Schema,详见HELP ALTER TABLE;
  5. 可以对 Table 增加上卷表(Rollup)以提高查询性能,这部分可以参见高级使用指南关于 Rollup 的描述。
  6. 表的列的Null属性默认为true,会对查询性能有一定的影响。

导入数据​

Doris 支持多种数据导入方式。具体可以参阅 数据导入 文档。这里我们使用流式导入和 Broker 导入做示例。

流式导入​

流式导入通过 HTTP 协议向 Doris 传输数据,可以不依赖其他系统或组件直接导入本地数据。详细语法帮助可以参阅 HELP STREAM LOAD;

示例1:以 "table1_20170707" 为 Label,使用本地文件 table1_data 导入 table1 表。

curl --location-trusted -u test:test_passwd -H "label:table1_20170707" -H "column_separator:," -T table1_data http://FE_HOST:8030/api/example_db/table1/_stream_load

  1. FE_HOST 是任一 FE 所在节点 IP,8030 为 fe.conf 中的 http_port。
  2. 可以使用任一 BE 的 IP,以及 be.conf 中的 webserver_port 进行导入。如:BE_HOST:8040

本地文件 table1_data 以 , 作为数据之间的分隔,具体内容如下:

1,1,jim,2
2,1,grace,2
3,2,tom,2
4,3,bush,3
5,3,helen,3

示例2: 以 "table2_20170707" 为 Label,使用本地文件 table2_data 导入 table2 表。

curl --location-trusted -u test:test -H "label:table2_20170707" -H "column_separator:|" -T table2_data http://127.0.0.1:8030/api/example_db/table2/_stream_load

本地文件 table2_data 以 | 作为数据之间的分隔,具体内容如下:

2017-07-03|1|1|jim|2
2017-07-05|2|1|grace|2
2017-07-12|3|2|tom|2
2017-07-15|4|3|bush|3
2017-07-12|5|3|helen|3

注意事项:

  1. 采用流式导入建议文件大小限制在 10GB 以内,过大的文件会导致失败重试代价变大。
  2. label:Label 的主要作用是唯一标识一个导入任务,并且能够保证相同的 Label 仅会被成功导入一次,具体可以查看 数据导入事务及原子性 。
  3. 流式导入是同步命令。命令返回成功则表示数据已经导入,返回失败表示这批数据没有导入。
Broker 导入​

Broker 导入通过部署的 Broker 进程,读取外部存储上的数据进行导入。更多帮助请参阅 HELP BROKER LOAD;

示例:以 "table1_20170708" 为 Label,将 HDFS 上的文件导入 table1 表

LOAD LABEL table1_20170708
(
    DATA INFILE("hdfs://your.namenode.host:port/dir/table1_data")
    INTO TABLE table1
)
WITH BROKER hdfs 
(
    "username"="hdfs_user",
    "password"="hdfs_password"
)
PROPERTIES
(
    "timeout"="3600",
    "max_filter_ratio"="0.1"
);

Broker 导入是异步命令。以上命令执行成功只表示提交任务成功。导入是否成功需要通过 SHOW LOAD; 查看。如:

SHOW LOAD WHERE LABEL = "table1_20170708";

返回结果中,State 字段为 FINISHED 则表示导入成功。

关于 SHOW LOAD 的更多说明,可以参阅 HELP SHOW LOAD;

异步的导入任务在结束前可以取消:

CANCEL LOAD WHERE LABEL = "table1_20170708";

数据的查询​

简单查询​

查询示例:

mysql> SELECT * FROM table1 LIMIT 3;
+--------+----------+----------+------+
| siteid | citycode | username | pv   |
+--------+----------+----------+------+
|      2 |        1 | 'grace'  |    2 |
|      5 |        3 | 'helen'  |    3 |
|      3 |        2 | 'tom'    |    2 |
+--------+----------+----------+------+
3 rows in set (0.01 sec)

mysql> SELECT * FROM table1 ORDER BY citycode;
+--------+----------+----------+------+
| siteid | citycode | username | pv   |
+--------+----------+----------+------+
|      2 |        1 | 'grace'  |    2 |
|      1 |        1 | 'jim'    |    2 |
|      3 |        2 | 'tom'    |    2 |
|      4 |        3 | 'bush'   |    3 |
|      5 |        3 | 'helen'  |    3 |
+--------+----------+----------+------+
5 rows in set (0.01 sec)

SELECT * EXCEPT​

SinceVersion 1.2

SELECT * EXCEPT 语句指定要从结果中排除的一个或多个列的名称。输出中将忽略所有匹配的列名称。

MySQL> SELECT * except (username, citycode) FROM table1;
+--------+------+
| siteid | pv   |
+--------+------+
|      2 |    2 |
|      5 |    3 |
|      3 |    2 |
+--------+------+
3 rows in set (0.01 sec)

注意SELECT * EXCEPT 不会排除没有名称的列。

Join 查询​

查询示例:

mysql> SELECT SUM(table1.pv) FROM table1 JOIN table2 WHERE table1.siteid = table2.siteid;
+--------------------+
| sum(`table1`.`pv`) |
+--------------------+
|                 12 |
+--------------------+
1 row in set (0.20 sec)

子查询​

查询示例:

mysql> SELECT SUM(pv) FROM table2 WHERE siteid IN (SELECT siteid FROM table1 WHERE siteid > 2);
+-----------+
| sum(`pv`) |
+-----------+
|         8 |
+-----------+
1 row in set (0.13 sec)

表结构变更​

使用 ALTER TABLE COLUMN 命令可以修改表的 Schema,包括如下修改:

  • 增加列
  • 删除列
  • 修改列类型
  • 改变列顺序

以下通过使用示例说明表结构变更:

原表 table1 的 Schema 如下:

+----------+-------------+------+-------+---------+-------+
| Field    | Type        | Null | Key   | Default | Extra |
+----------+-------------+------+-------+---------+-------+
| siteid   | int(11)     | No   | true  | 10      |       |
| citycode | smallint(6) | No   | true  | N/A     |       |
| username | varchar(32) | No   | true  |         |       |
| pv       | bigint(20)  | No   | false | 0       | SUM   |
+----------+-------------+------+-------+---------+-------+

我们新增一列 uv,类型为 BIGINT,聚合类型为 SUM,默认值为 0:

ALTER TABLE table1 ADD COLUMN uv BIGINT SUM DEFAULT '0' after pv;

提交成功后,可以通过以下命令查看作业进度:

SHOW ALTER TABLE COLUMN;

当作业状态为 FINISHED,则表示作业完成。新的 Schema 已生效。

ALTER TABLE 完成之后, 可以通过 DESC TABLE 查看最新的 Schema。

mysql> DESC table1;
+----------+-------------+------+-------+---------+-------+
| Field    | Type        | Null | Key   | Default | Extra |
+----------+-------------+------+-------+---------+-------+
| siteid   | int(11)     | No   | true  | 10      |       |
| citycode | smallint(6) | No   | true  | N/A     |       |
| username | varchar(32) | No   | true  |         |       |
| pv       | bigint(20)  | No   | false | 0       | SUM   |
| uv       | bigint(20)  | No   | false | 0       | SUM   |
+----------+-------------+------+-------+---------+-------+
5 rows in set (0.00 sec)

可以使用以下命令取消当前正在执行的作业:

CANCEL ALTER TABLE COLUMN FROM table1;

更多帮助,可以参阅 HELP ALTER TABLE

Rollup​

Rollup 可以理解为 Table 的一个物化索引结构。物化 是因为其数据在物理上独立存储,而 索引 的意思是,Rollup可以调整列顺序以增加前缀索引的命中率,也可以减少key列以增加数据的聚合度。

使用ALTER TABLE ROLLUP可以进行Rollup的各种变更操作。

以下举例说明

原表table1的Schema如下:

+----------+-------------+------+-------+---------+-------+
| Field    | Type        | Null | Key   | Default | Extra |
+----------+-------------+------+-------+---------+-------+
| siteid   | int(11)     | No   | true  | 10      |       |
| citycode | smallint(6) | No   | true  | N/A     |       |
| username | varchar(32) | No   | true  |         |       |
| pv       | bigint(20)  | No   | false | 0       | SUM   |
| uv       | bigint(20)  | No   | false | 0       | SUM   |`
+----------+-------------+------+-------+---------+-------+

对于 table1 明细数据是 siteid, citycode, username 三者构成一组 key,从而对 pv 字段进行聚合;如果业务方经常有看城市 pv 总量的需求,可以建立一个只有 citycode, pv 的rollup。

ALTER TABLE table1 ADD ROLLUP rollup_city(citycode, pv);

提交成功后,可以通过以下命令查看作业进度:

SHOW ALTER TABLE ROLLUP;

当作业状态为 FINISHED,则表示作业完成。

Rollup 建立完成之后可以使用 DESC table1 ALL 查看表的 Rollup 信息。

mysql> desc table1 all;
+-------------+----------+-------------+------+-------+--------+-------+
| IndexName   | Field    | Type        | Null | Key   | Default | Extra |
+-------------+----------+-------------+------+-------+---------+-------+
| table1      | siteid   | int(11)     | No   | true  | 10      |       |
|             | citycode | smallint(6) | No   | true  | N/A     |       |
|             | username | varchar(32) | No   | true  |         |       |
|             | pv       | bigint(20)  | No   | false | 0       | SUM   |
|             | uv       | bigint(20)  | No   | false | 0       | SUM   |
|             |          |             |      |       |         |       |
| rollup_city | citycode | smallint(6) | No   | true  | N/A     |       |
|             | pv       | bigint(20)  | No   | false | 0       | SUM   |
+-------------+----------+-------------+------+-------+---------+-------+
8 rows in set (0.01 sec)

可以使用以下命令取消当前正在执行的作业:

CANCEL ALTER TABLE ROLLUP FROM table1;

Rollup 建立之后,查询不需要指定 Rollup 进行查询。还是指定原有表进行查询即可。程序会自动判断是否应该使用 Rollup。是否命中 Rollup可以通过 EXPLAIN your_sql; 命令进行查看。

更多帮助,可以参阅 HELP ALTER TABLE

物化视图​

物化视图是一种以空间换时间的数据分析加速技术。Doris 支持在基础表之上建立物化视图。比如可以在明细数据模型的表上建立基于部分列的聚合视图,这样可以同时满足对明细数据和聚合数据的快速查询。

同时,Doris 能够自动保证物化视图和基础表的数据一致性,并且在查询时自动匹配合适的物化视图,极大降低用户的数据维护成本,为用户提供一个一致且透明的查询加速体验。

关于物化视图的具体介绍,可参阅 物化视图

数据表的查询​

内存限制​

为了防止用户的一个查询可能因为消耗内存过大。查询进行了内存控制,一个查询任务,在单个 BE 节点上默认使用不超过 2GB 内存。

用户在使用时,如果发现报 Memory limit exceeded 错误,一般是超过内存限制了。

遇到内存超限时,用户应该尽量通过优化自己的 sql 语句来解决。

如果确切发现2GB内存不能满足,可以手动设置内存参数。

显示查询内存限制:

mysql> SHOW VARIABLES LIKE "%mem_limit%";
+---------------+------------+
| Variable_name | Value      |
+---------------+------------+
| exec_mem_limit| 2147483648 |
+---------------+------------+
1 row in set (0.00 sec)

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

mysql> SET exec_mem_limit = 8589934592;
Query OK, 0 rows affected (0.00 sec)
mysql> SHOW VARIABLES LIKE "%mem_limit%";
+---------------+------------+
| Variable_name | Value      |
+---------------+------------+
| exec_mem_limit| 8589934592 |
+---------------+------------+
1 row in set (0.00 sec)
  • 以上该修改为 session 级别,仅在当前连接 session 内有效。断开重连则会变回默认值。
  • 如果需要修改全局变量,可以这样设置:SET GLOBAL exec_mem_limit = 8589934592;。设置完成后,断开 session 重新登录,参数将永久生效。

查询超时​

当前默认查询时间设置为最长为 300 秒,如果一个查询在 300 秒内没有完成,则查询会被 Doris 系统 cancel 掉。用户可以通过这个参数来定制自己应用的超时时间,实现类似 wait(timeout) 的阻塞方式。

查看当前超时设置:

mysql> SHOW VARIABLES LIKE "%query_timeout%";
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| QUERY_TIMEOUT | 300   |
+---------------+-------+
1 row in set (0.00 sec)

修改超时时间到1分钟:

mysql>  SET query_timeout = 60;
Query OK, 0 rows affected (0.00 sec)
  • 当前超时的检查间隔为 5 秒,所以小于 5 秒的超时不会太准确。
  • 以上修改同样为 session 级别。可以通过 SET GLOBAL 修改全局有效。

Broadcast/Shuffle Join​

系统默认实现 Join 的方式,是将小表进行条件过滤后,将其广播到大表所在的各个节点上,形成一个内存 Hash 表,然后流式读出大表的数据进行Hash Join。但是如果当小表过滤后的数据量无法放入内存的话,此时 Join 将无法完成,通常的报错应该是首先造成内存超限。

如果遇到上述情况,建议显式指定 Shuffle Join,也被称作 Partitioned Join。即将小表和大表都按照 Join 的 key 进行 Hash,然后进行分布式的 Join。这个对内存的消耗就会分摊到集群的所有计算节点上。

Doris会自动尝试进行 Broadcast Join,如果预估小表过大则会自动切换至 Shuffle Join。注意,如果此时显式指定了 Broadcast Join,则会强制执行 Broadcast Join。

使用 Broadcast Join(默认):

mysql> select sum(table1.pv) from table1 join table2 where table1.siteid = 2;
+--------------------+
| sum(`table1`.`pv`) |
+--------------------+
|                 10 |
+--------------------+
1 row in set (0.20 sec)

使用 Broadcast Join(显式指定):

mysql> select sum(table1.pv) from table1 join [broadcast] table2 where table1.siteid = 2;
+--------------------+
| sum(`table1`.`pv`) |
+--------------------+
|                 10 |
+--------------------+
1 row in set (0.20 sec)

使用 Shuffle Join:

mysql> select sum(table1.pv) from table1 join [shuffle] table2 where table1.siteid = 2;
+--------------------+
| sum(`table1`.`pv`) |
+--------------------+
|                 10 |
+--------------------+
1 row in set (0.15 sec)

查询重试和高可用​

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

数据更新和删除​

Doris 支持通过两种方式对已导入的数据进行删除。一种是通过 DELETE FROM 语句,指定 WHERE 条件对数据进行删除。这种方式比较通用,适合频率较低的定时删除任务。

另一种删除方式仅针对 Unique 主键唯一模型,通过导入数据的方式将需要删除的主键行数据进行导入。Doris 内部会通过删除标记位对数据进行最终的物理删除。这种删除方式适合以实时的方式对数据进行删除。

你可能感兴趣的:(apache,数据库,mysql,系统架构,算法,大数据)