在数据库应用过程中,我们经常会有数据导出需求。目前,Doris支持3种方式导出数据。
EXPORT是Doris提供的一种将数据导出的命令。该命令可以将用户指定的表或分区中的数据以文本格式,通过Broker进程导出到远端存储系统,如HDFS、BOS等。目前,该方式仅支持对指定表或分区进行全量导出,不支持对导出结果进行映射、过滤或转换操作,导出格式为CSV。导出文件到BOS需要使用S3兼容协议。
在提交导出任务以后,我们可以通过SHOW命令查看执行中的导出任务,并按StartTime降序排序。
导出完成以后,我们登录BOS控制台,可以看到导出文件是一个文件夹,截图如图10-2所示。
下载文件并打开后,我们可发现是由tab符分割的文本文件,生成文件夹只是为了多节点并行执行。SELECT INTO OUTFILE语句支持将查询结果导出到文件中。目前,Doris支持通过Broker进程将查询结果导出到远端存储系统,如HDFS、S3、BOS,或者直接导出到FE节点的本地磁盘(云上不支持)。用户可以通过该语句,借助灵活的SQL语法,导出期望的查询结果。但受限于最终结果的单线程产出,效率要低于EXPORT命令方式。导出数据到本地磁盘需要在FE节点上增加参数enable_outfile_to_local=true。SELECT INTO OUTFILE语句本质上是一个同步执行的SQL查询命令,因此会受到会话变量query_timeout的超时限制。如果导出较大结果集或SQL本身执行时间较长,请先设置合理的超时时间。例如,导出数据到Doris FE节点的本地磁盘,截图如10-3所示。

图10-3 导出数据到Doris FE节点的本地磁盘Doris支持通过INSERT命令直接将数据写入ODBC外部表,操作过程和数据写入内部表一样。写入操作是以单ODBC客户端连接方式实现的,因此不建议一次性提交大量数据。继续利用原来创建的MySQL外部表odbc_event_log,向表中写入数据。

另外,设置会话变量enable_odbc_transaction为true,可以开启事务支持。事务支持可以保证数据写入的原子性,不会出现只有部分数据写入的情况。但是开启事务支持会降低写入效率,请权衡考虑。数据资产概念的提出表明数据价值得到充分重视。为了避免数据异常丢失,我们需要充分做好数据备份工作。在备份足够快的情况下,我们可以每周备份一次全量数据,每天备份一次关键数据。Doris支持将当前数据以文件的形式,通过Broker进程备份到远端存储系统。之后,我们可以通过恢复命令,从远端存储系统中将数据恢复到任意Doris集群。通过这个功能,Doris可以支持将数据定期进行快照备份,也可以在不同集群间进行数据迁移。备份操作是将指定表或分区的数据,直接以Doris文件存储形式,上传到远端存储系统进行存储。当用户提交Backup请求后,系统内部会做如下操作。1)快照及快照上传。快照阶段会对指定的表或分区数据文件进行快照。之后,备份都是对快照文件进行操作。在快照之后,对表进行的更改、导入等操作都不再影响备份。快照只是对当前数据文件产生一个硬链,耗时很短。快照完成后,开始对这些快照文件进行逐一上传。快照上传由各个Backend进程并发完成。2)元数据准备及上传。快照文件上传完成后,Frontend进程会首先将对应元数据写入本地文件,然后通过Broker进程将本地元数据文件上传到远端存储系统,完成最终备份作业。3)动态分区表说明。如果该表是动态分区表,备份之后会自动禁用动态分区属性,在做恢复的时候需要手动将该表的动态分区属性启用,命令如下:
4)备份和恢复操作都不会保留表的colocate_with属性。创建一个BOS远端存储系统,并将数据库表example_tbl中的数据备份到远端存储系统中。
提交备份任务以后,我们还可以通过SHOW BACKUP命令查看最近Backup作业的执行情况,也可以通过SHOW SNAPSHOT ON bos_repo WHERE SNAPSHOT="snapshot_label2"查看远端存储系统中已存在的备份快照,截图如图10-5所示。
Doris支持最小分区粒度的全量备份(增量备份有可能在Doris未来版本支持)。当表的数据量很大时,建议按分区分别执行,以减小失败重试的代价。如果需要对数据进行定期备份,首先需要在建表时合理规划表的分区分桶,比如按时间进行分区,然后在之后的运行过程中,按照分区粒度定期进行数据备份。因为备份操作的都是实际的数据文件,所以当一个表的分片过多,或者一个分片有过多的文件时,可能即使总数据量很小,依然需要很长时间。用户可以通过SHOW PARTITIONS FROM table_name;和SHOW TABLET FROM table_name;来查看各个分区的分片数量以及各个分片的文件数量,预估作业执行时间。文件数量对作业执行时间影响非常大,所以建议在建表时合理规划分区分桶,以避免过多的分片。一个数据库内只允许有一个正在执行的备份作业。当通过SHOW BACKUP或者SHOW RESTORE命令查看作业状态时,我们有可能会在TaskErrMsg一列中看到错误信息。但只要State列不为CANCELLED,就说明作业依然在继续,这些作业有可能会重试成功。当然,有些错误会直接导致作业失败。数据恢复操作需要指定一个远端仓库中已存在的备份,然后将这个备份的内容恢复到本地集群。当用户提交Restore请求后,系统内部会做如下操作。1)在本地创建对应的元数据。这一步首先会在本地集群中创建数据恢复对应的表分区等结构。创建完成后,该表可见,但是不可访问。2)在本地执行快照。这一步是对第一步创建的表进行快照。这其实是一个空快照(因为刚创建的表是没有数据的),目的主要是在Backend进程中产生对应的快照目录,以便之后接收从远端仓库下载的快照文件。3)下载快照。远端仓库中的快照文件会被下载到第二步生成的快照目录中。这一步由各个Backend进程并发完成。4)快照生效。快照下载完成后,我们要将各个快照映射为当前本地表的元数据,然后重新加载这些快照,使之生效,完成最终的数据恢复作业。从前面bos_repo的备份中恢复表数据,语句如下。
如果恢复作业是一次覆盖操作(指定恢复数据到已经存在的表或分区),那么从数据恢复作业的提交阶段开始,当前集群上被覆盖的数据有可能不能再被还原。此时,如果恢复作业失败或被取消,有可能造成之前的数据损坏且无法访问。在这种情况下,只能通过再次执行恢复操作,并等待作业完成。因此,建议如无必要,尽量不要使用覆盖方式恢复数据,除非确认当前数据已不再使用。
Python作为数据分析最常用的编程语言和脚本语言,也可以很方便地通过MySQL插件连接Doris进行各种操作。下面给出一个具体的案例,通过Python脚本配合Linux Cron表达式,实现每天3次定时备份Doris数据库里面的表、视图等对象的创建语句。这在数据仓库开发中具有非常重要的意义。
通过Python脚本定时备份Doris的元数据信息和视图创建语句,以便开发过程中进行版本追溯。


选择一个FE节点部署程序,设置Cron定时任务,每天早中晚备份3次代码,以有效避免代码被覆盖或者表结构被误删。

参考:Doris实时数仓实战:https://weread.qq.com/web/reader/e3432570813ab8029g019a69k1f032c402131f0e3dad99f3