深入Doris实时数仓:导入本地数据

本文涉及的产品
RDS MySQL DuckDB 分析主实例,基础系列 4核8GB
RDS MySQL DuckDB 分析主实例,集群系列 4核8GB
RDS AI 助手,专业版
简介: 深入Doris实时数仓:导入本地数据

一、Doris数据导入总览

支持的数据源

Doris 提供多种数据导入方案,可以针对不同的数据源进行选择不同的数据导入方式。

按场景划分

数据源 导入方式
对象存储(s3),HDFS 使用Broker导入数据
本地文件 导入本地数据
Kafka 订阅Kafka数据
Mysql、PostgreSQL,Oracle,SQLServer 通过外部表同步数据
通过JDBC导入 使用JDBC同步数据
导入JSON格式数据 JSON格式数据导入

按导入方式划分

导入方式名称 使用方式
Spark Load 通过Spark导入外部数据
Broker Load 通过Broker导入外部存储数据
Stream Load 流式导入数据(本地文件及内存数据)
Routine Load 导入Kafka数据
Insert Into 外部表通过INSERT方式导入数据
S3 Load S3协议的对象存储数据导入
MySQL Load MySQL客户端导入本地数据

支持的数据格式

不同的导入方式支持的数据格式略有不同。

导入方式 支持的格式
Broker Load parquet、orc、csv、gzip
Stream Load csv、json、parquet、orc
Routine Load csv、json
MySQL Load csv

导入的原子性保证

Doris 的每一个导入作业,不论是使用 Broker Load 进行批量导入,还是使用 INSERT 语句进行单条导入,都是一个完整的事务操作。导入事务可以保证一批次内的数据原子生效,不会出现部分数据写入的情况。

同时,一个导入作业都会有一个 Label。这个 Label 是在一个数据库(Database)下唯一的,用于唯一标识一个导入作业。Label 可以由用户指定,部分导入功能也会由系统自动生成。


Label 是用于保证对应的导入作业,仅能成功导入一次。一个被成功导入的 Label,再次使用时,会被拒绝并报错 Label already used。通过这个机制,可以在 Doris 侧做到 At-Most-Once 语义。如果结合上游系统的 At-Least-Once 语义,则可以实现导入数据的 Exactly-Once 语义。


关于原子性保证的最佳实践,可以参阅 导入事务和原子性。

同步及异步导入

导入方式分为同步和异步。对于同步导入方式,返回结果即表示导入成功还是失败。而对于异步导入方式,返回成功仅代表作业提交成功,不代表数据导入成功,需要使用对应的命令查看导入作业的运行状态。

目前Doris支持两种从本地导入数据的模式:

  • Stream Load
  • MySQL Load

二、本地导入的Stream Load模式

Stream Load 用于将本地文件导入到 Doris 中。

2.1 Stream Load原理

Stream load 是一个同步的导入方式,用户通过发送 HTTP 协议发送请求将本地文件或数据流导入到 Doris 中。Stream load 同步执行导入并返回导入结果。用户可直接通过请求的返回体判断本次导入是否成功。

Stream load 主要适用于导入本地文件,或通过程序导入数据流中的数据。


相比于直接使用 curl 的单并发导入,更推荐使用 专用导入工具 Doris Streamloader 该工具是一款用于将数据导入 Doris 数据库的专用客户端工具,可以提供 多并发导入 的功能,降低大数据量导入的耗时。拥有以下功能:


并发导入,实现 Stream Load 的多并发导入。可以通过 workers 值设置并发数。

多文件导入,一次导入可以同时导入多个文件及目录,支持设置通配符以及会自动递归获取文件夹下的所有文件。

断点续传,在导入过程中可能出现部分失败的情况,支持在失败点处进行继续传输。

自动重传,在导入出现失败的情况后,无需手动重传,工具会自动重传默认的次数,如果仍然不成功,打印出手动重传的命令。

不同于其他命令的提交方式,Stream Load 是通过 HTTP 协议与 Doris 进行连接交互的。


该方式中涉及 HOST:PORT 应为 HTTP 协议端口。


BE 的 HTTP 协议端口,默认为 8040。

FE 的 HTTP 协议端口,默认为 8030。但须保证客户端所在机器网络能够联通 BE 所在机器。

本文文档我们以 curl 命令为例演示如何进行数据导入。


文档最后,我们给出一个使用 Java 导入数据的代码示例

2.2 导入数据

Stream Load 的请求体如下:

PUT /api/{db}/{table}/_stream_load

1. 创建一张表

通过 CREATE TABLE 命令在demo创建一张表用于存储待导入的数据。具体的导入方式请查阅 CREATE TABLE 命令手册。示例如下:

CREATE TABLE IF NOT EXISTS load_local_file_test
(
    id INT,
    age TINYINT,
    name VARCHAR(50)
)
unique key(id)
DISTRIBUTED BY HASH(id) BUCKETS 3;

2. 导入数据

执行以下 curl 命令导入本地文件:

 curl -u user:passwd -H "label:load_local_file_test" -T /path/to/local/demo.txt http://host:port/api/demo/load_local_file_test/_stream_load

user:passwd 为在 Doris 中创建的用户。初始用户为 admin / root,密码初始状态下为空。

host:port 为 BE 的 HTTP 协议端口,默认是 8040,可以在 Doris 集群 WEB UI页面查看。

label: 可以在 Header 中指定 Label 唯一标识这个导入任务。

关于 Stream Load 命令的更多高级操作,请参阅 Stream Load 命令文档。

3. 等待导入结果

Stream Load 命令是同步命令,返回成功即表示导入成功。如果导入数据较大,可能需要较长的等待时间。示例如下:

{
    "TxnId": 1003,
    "Label": "load_local_file_test",
    "Status": "Success",
    "Message": "OK",
    "NumberTotalRows": 1000000,
    "NumberLoadedRows": 1000000,
    "NumberFilteredRows": 1,
    "NumberUnselectedRows": 0,
    "LoadBytes": 40888898,
    "LoadTimeMs": 2144,
    "BeginTxnTimeMs": 1,
    "StreamLoadPutTimeMs": 2,
    "ReadDataTimeMs": 325,
    "WriteDataTimeMs": 1933,
    "CommitAndPublishTimeMs": 106,
    "ErrorURL": "http://192.168.1.1:8042/api/_load_error_log?file=__shard_0/error_log_insert_stmt_db18266d4d9b4ee5-abb00ddd64bdf005_db18266d4d9b4ee5_abb00ddd64bdf005"
}
  • Status 字段状态为 Success 即表示导入成功。
  • 其他字段的详细介绍,请参阅 Stream Load 命令文档。

导入建议

Stream Load 只能导入本地文件。

建议一个导入请求的数据量控制在 1 - 2 GB 以内。如果有大量本地文件,可以分批并发提交。

Java 代码示例

这里通过一个简单的 JAVA 示例来执行 Stream Load:

package demo.doris;

import org.apache.commons.codec.binary.Base64;
import org.apache.http.HttpHeaders;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.FileEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultRedirectStrategy;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

/*
这是一个 Doris Stream Load 示例,需要依赖
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.13</version>
</dependency>
 */
public class DorisStreamLoader {
    //可以选择填写 FE 地址以及 FE 的 http_port,但须保证客户端和 BE 节点的连通性。
    private final static String HOST = "your_host";
    private final static int PORT = 8040;
    private final static String DATABASE = "db1";   // 要导入的数据库
    private final static String TABLE = "tbl1";     // 要导入的表
    private final static String USER = "root";      // Doris 用户名
    private final static String PASSWD = "";        // Doris 密码
    private final static String LOAD_FILE_NAME = "/path/to/1.txt"; // 要导入的本地文件路径

    private final static String loadUrl = String.format("http://%s:%s/api/%s/%s/_stream_load",
            HOST, PORT, DATABASE, TABLE);

    private final static HttpClientBuilder httpClientBuilder = HttpClients
            .custom()
            .setRedirectStrategy(new DefaultRedirectStrategy() {
                @Override
                protected boolean isRedirectable(String method) {
                    // 如果连接目标是 FE,则需要处理 307 redirect。
                    return true;
                }
            });

    public void load(File file) throws Exception {
        try (CloseableHttpClient client = httpClientBuilder.build()) {
            HttpPut put = new HttpPut(loadUrl);
            put.setHeader(HttpHeaders.EXPECT, "100-continue");
            put.setHeader(HttpHeaders.AUTHORIZATION, basicAuthHeader(USER, PASSWD));

            // 可以在 Header 中设置 stream load 相关属性,这里我们设置 label 和 column_separator。
            put.setHeader("label","label1");
            put.setHeader("column_separator",",");

            // 设置导入文件。
            // 这里也可以使用 StringEntity 来传输任意数据。
            FileEntity entity = new FileEntity(file);
            put.setEntity(entity);

            try (CloseableHttpResponse response = client.execute(put)) {
                String loadResult = "";
                if (response.getEntity() != null) {
                    loadResult = EntityUtils.toString(response.getEntity());
                }

                final int statusCode = response.getStatusLine().getStatusCode();
                if (statusCode != 200) {
                    throw new IOException(
                            String.format("Stream load failed. status: %s load result: %s", statusCode, loadResult));
                }

                System.out.println("Get load result: " + loadResult);
            }
        }
    }

    private String basicAuthHeader(String username, String password) {
        final String tobeEncode = username + ":" + password;
        byte[] encoded = Base64.encodeBase64(tobeEncode.getBytes(StandardCharsets.UTF_8));
        return "Basic " + new String(encoded);
    }

    public static void main(String[] args) throws Exception{
        DorisStreamLoader loader = new DorisStreamLoader();
        File file = new File(LOAD_FILE_NAME);
        loader.load(file);
    }
}

注意:这里 http client 的版本要是4.5.13

<dependency>
   <groupId>org.apache.httpcomponents</groupId>
   <artifactId>httpclient</artifactId>
   <version>4.5.13</version>
</dependency>

三、本地导入的MySQL Load模式

该语句兼容MySQL标准的LOAD DATA语法,方便用户导入本地数据,并降低学习成本。

MySQL Load 同步执行导入并返回导入结果。用户可直接通过SQL返回信息判断本次导入是否成功。

MySQL Load 主要适用于导入客户端本地文件,或通过程序导入数据流中的数据。

3.1 基本原理

MySQL Load和Stream Load功能相似, 都是导入本地文件到Doris集群中, 因此MySQL Load实现复用了StreamLoad的基础导入能力:

  • FE接收到客户端执行的MySQL Load请求, 完成SQL解析工作
  • FE将Load请求拆解,并封装为StreamLoad的请求.
  • FE选择一个BE节点发送StreamLoad请求
  • 发送请求的同时, FE会异步且流式的从MySQL客户端读取本地文件数据, 并实时的发送到StreamLoad的HTTP请求中.
  • MySQL客户端数据传输完毕, FE等待StreamLoad完成, 并展示导入成功或者失败的信息给客户端.

3.2 导入数据

1. 创建一张表

通过 CREATE TABLE 命令在demo创建一张表用于存储待导入的数据

CREATE TABLE IF NOT EXISTS load_local_file_test
(
id INT,
age TINYINT,
name VARCHAR(50)
)
unique key(id)
DISTRIBUTED BY HASH(id) BUCKETS 3;

2. 导入数据 在MySQL客户端下执行以下 SQL 命令导入本地文件:

LOAD DATA
LOCAL
INFILE '/path/to/local/demo.txt'
INTO TABLE demo.load_local_file_test

关于 MySQL Load 命令的更多高级操作,请参阅 MySQL Load 命令文档。

3. 等待导入结果

MySQL Load 命令是同步命令,返回成功即表示导入成功。如果导入数据较大,可能需要较长的等待时间。示例如下:

Query OK, 1 row affected (0.17 sec)
Records: 1  Deleted: 0  Skipped: 0  Warnings: 0
  • 如果出现上述结果, 则表示导入成功。导入失败, 会抛出错误,并在客户端显示错误原因
  • 其他字段的详细介绍,请参阅 MySQL Load 命令文档。

4. 导入建议

  • MySQL Load 只能导入本地文件(可以是客户端本地或者连接的FE节点本地), 而且支持CSV格式。
  • 建议一个导入请求的数据量控制在 1 - 2 GB 以内。如果有大量本地文件,可以分批并发提交。

四、实时数仓结合机器学习、大模型的发展趋势

智能化实时数据处理与分析

实时数据处理与机器学习的结合:随着机器学习技术的不断发展,未来的实时数仓将更加注重与机器学习算法的结合。通过引入机器学习模型,实时数仓能够实现对数据的实时分析和预测,为企业提供即时的业务洞察。例如,在零售行业中,通过机器学习模型对实时销售数据进行分析,可以预测未来的销售趋势,从而及时调整库存和营销策略。


大模型的应用:大模型,尤其是基石模型等先进的人工智能工具,将在实时数仓中发挥重要作用。这些模型具有强大的数据处理和分析能力,能够处理海量的实时数据,并从中提取有价值的信息。通过与实时数仓的结合,大模型可以实现更高效的数据处理和更精准的预测分析。

增强数据质量和数据治理

数据清洗与验证:机器学习算法可以用于实时数据的清洗和验证,确保进入实时数仓的数据质量。通过训练模型来识别异常数据、纠正错误,并自动进行数据标准化和归一化处理,从而提高数据的准确性和可靠性。


数据治理的智能化:结合机器学习技术,实时数仓可以实现更智能的数据治理。例如,利用算法对数据进行分类、标签化和归档,以便更好地组织和管理数据。同时,通过监控数据的使用情况和访问权限,确保数据的安全性和合规性。

优化性能和降低成本

性能优化:机器学习技术可以用于优化实时数仓的性能。通过训练模型来预测数据访问模式和查询需求,从而自动调整数据存储和索引策略,提高数据查询和处理的速度。此外,还可以利用机器学习技术对硬件资源进行智能调度和优化,以提高实时数仓的整体性能。


降低成本:通过机器学习技术的引入,实时数仓可以更加高效地利用存储和计算资源,从而降低运营成本。例如,利用预测模型来优化数据存储策略,减少不必要的数据冗余和存储开销。同时,通过智能调度算法来合理分配计算资源,提高资源利用率并降低能耗。


综上所述,实时数仓与机器学习、大模型的结合将推动数据处理和分析的智能化、高效化和安全化发展。这将为企业提供更准确、更及时的业务洞察和决策支持,助力企业在快速变化的市场环境中保持竞争优势。


相关实践学习
基于Hologres轻量实时的高性能OLAP分析
本教程基于GitHub Archive公开数据集,通过DataWorks将GitHub中的项⽬、行为等20多种事件类型数据实时采集至Hologres进行分析,同时使用DataV内置模板,快速搭建实时可视化数据大屏,从开发者、项⽬、编程语⾔等多个维度了解GitHub实时数据变化情况。
相关文章
|
8月前
|
消息中间件 OLAP Kafka
Apache Doris 实时更新技术揭秘:为何在 OLAP 领域表现卓越?
Apache Doris 为何在 OLAP 领域表现卓越?凭借其主键模型、数据延迟、查询性能、并发处理、易用性等多方面特性的表现,在分析领域展现了独特的实时更新能力。
727 9
|
9月前
|
运维 算法 机器人
阿里云AnalyticDB具身智能方案:破解机器人仿真数据、算力与运维之困
本文将介绍阿里云瑶池旗下的云原生数据仓库AnalyticDB MySQL推出的全托管云上仿真解决方案,方案采用云原生架构,为开发者提供从开发环境、仿真计算到数据管理的全链路支持。
|
11月前
|
SQL 存储 缓存
顺丰科技:从 Presto 到 Doris 湖仓构架升级,提速 3 倍,降本 48%
顺丰科技引入 Doris 替换 Presto,在内部可视化数据自助分析工具丰景台场景广泛应用。目前,顺丰临时查询业务、丰景台报表业务的 Presto 场景已经 100% 切换到 Doris 集群中,日均查询量 100W+。并实现 P95 性能提升近 3 倍,硬件资源节省达 48% 显著收益。
327 9
顺丰科技:从 Presto 到 Doris 湖仓构架升级,提速 3 倍,降本 48%
|
7月前
|
存储 自然语言处理 分布式计算
Apache Doris 3.1 正式发布:半结构化分析全面升级,湖仓一体能力再跃新高
Apache Doris 3.1 正式发布!全面升级半结构化分析,支持 VARIANT 稀疏列与模板化 Schema,提升湖仓一体能力,增强 Iceberg/Paimon 集成,优化存储引擎与查询性能,助力高效数据分析。
889 4
Apache Doris 3.1 正式发布:半结构化分析全面升级,湖仓一体能力再跃新高
|
8月前
|
SQL 存储 运维
Apache Doris 在菜鸟的大规模湖仓业务场景落地实践
本文介绍了 Apache Doris 在菜鸟的大规模落地的实践经验,菜鸟为什么选择 Doris,以及 Doris 如何在菜鸟从 0 开始,一步步的验证、落地,到如今上万核的规模,服务于各个业务线,Doris 已然成为菜鸟 OLAP 数据分析的最优选型。
460 2
Apache Doris 在菜鸟的大规模湖仓业务场景落地实践
|
存储 SQL 缓存
快手:从 Clickhouse 到 Apache Doris,实现湖仓分离向湖仓一体架构升级
快手 OLAP 系统为内外多个场景提供数据服务,每天承载近 10 亿的查询请求。原有湖仓分离架构,由离线数据湖和实时数仓组成,面临存储冗余、资源抢占、治理复杂、查询调优难等问题。通过引入 Apache Doris 湖仓一体能力,替换了 Clickhouse ,升级为湖仓一体架构,并结合 Doris 的物化视图改写能力和自动物化服务,实现高性能的数据查询以及灵活的数据治理。
971 3
快手:从 Clickhouse 到 Apache Doris,实现湖仓分离向湖仓一体架构升级
|
存储 缓存 数据挖掘
Flink + Doris 实时湖仓解决方案
本文整理自SelectDB技术副总裁陈明雨在Flink Forward Asia 2024的分享,聚焦Apache Doris与湖仓一体解决方案。内容涵盖三部分:一是介绍Apache Doris,一款高性能实时分析数据库,支持多场景应用;二是基于Doris、Flink和Paimon的湖仓解决方案,解决批流融合与数据一致性挑战;三是Doris社区生态及云原生发展,包括存算分离架构与600多位贡献者的活跃社区。文章深入探讨了Doris在性能、易用性及场景支持上的优势,并展示了其在多维分析、日志分析和湖仓分析中的实际应用案例。
1098 17
Flink + Doris 实时湖仓解决方案
|
12月前
|
SQL 分布式数据库 Apache
网易游戏 x Apache Doris:湖仓一体架构演进之路
网易游戏 Apache Doris 集群超 20 个 ,总节点数百个,已对接内部 200+ 项目,日均查询量超过 1500 万,总存储数据量 PB 级别。
1038 3
网易游戏 x Apache Doris:湖仓一体架构演进之路
|
存储 SQL 关系型数据库
拉卡拉 x Apache Doris:统一金融场景 OLAP 引擎,查询提速 15 倍,资源直降 52%
拉卡拉早期基于 Lambda 架构构建数据系统面临存储成本高、实时写入性能差、复杂查询耗时久、组件维护复杂等问题。为此,拉卡拉选择使用 Apache Doris 替换 Elasticsearch、Hive、Hbase、TiDB、Oracle / MySQL 等组件,实现了 OLAP 引擎的统一、查询性能提升 15 倍、资源减少 52% 的显著成效。
612 6
拉卡拉 x Apache Doris:统一金融场景 OLAP 引擎,查询提速 15 倍,资源直降 52%

热门文章

最新文章