starrocks使用 INSERT INTO FILES 导出数据为CSV/Parquet文件

准备工作

以下示例创建了一个名为 unload 的数据库和一个名为 sales_records 的表,作为以下教程中使用的数据对象。您也可以使用自己的数据作为替代。

CREATE DATABASE unload;
USE unload;
CREATE TABLE sales_records(
    record_id     BIGINT,
    seller        STRING,
    store_id      INT,
    sales_time    DATETIME,
    sales_amt     DOUBLE
)
DUPLICATE KEY(record_id)
PARTITION BY date_trunc('day', sales_time)
DISTRIBUTED BY HASH(record_id);

INSERT INTO sales_records
VALUES
    (220313001,"Amy",1,"2022-03-13 12:00:00",8573.25),
    (220314002,"Bob",2,"2022-03-14 12:00:00",6948.99),
    (220314003,"Amy",1,"2022-03-14 12:00:00",4319.01),
    (220315004,"Carl",3,"2022-03-15 12:00:00",8734.26),
    (220316005,"Carl",3,"2022-03-16 12:00:00",4212.69),
    (220317006,"Bob",2,"2022-03-17 12:00:00",9515.88);

sales_records 包含了每个交易的交易 ID record_id、销售人员 seller、商店 ID store_id、时间 sales_time 和销售额 sales_amt。该表根据 sales_time 以日为单位分区。

此外,您还需要准备一个具有写权限的远程存储系统。以下示例使用了两种远程存储系统:

  • 启用了简单验证的 HDFS 集群。

  • 通过 IAM User 认证介入 AWS S3 储存空间。

有关 FILES() 支持的远程存储系统和认证方法,请参阅 SQL参考 - FILES()

导出数据

INSERT INTO FILES 支持将数据导出到单个文件或多个文件。您可以通过为这些文件指定不同的存储路径来进一步分区。

在使用 INSERT INTO FILES 导出数据时,您必须通过设置 compression 属性手动设置压缩算法。有关数据导出支持的压缩算法,请参阅 unload_data_param

导出数据到多个文件

默认情况下,INSERT INTO FILES 会将数据导出到多个数据文件中,每个文件的大小为 1 GB。您可以使用target_max_file_size 属性配置文件大小, 单位是 Byte。

以下示例将 sales_records 中的所有数据行导出为多个以 data1 为前缀的 Parquet 文件。每个文件的大小为 1 KB。

备注

此处将 target_max_file_size 设置为 1 KB 是为了通过小数据集演示导入到多个文件中。在生产环境中,强烈建议将该值设置在几百 MB 到几 GB 的范围内。

  • 导出至 S3:
INSERT INTO 
FILES(
    "path" = "s3://mybucket/unload/data1",
    "format" = "parquet",
    "compression" = "uncompressed",
    "target_max_file_size" = "1024", -- 1KB
    "aws.s3.access_key" = "xxxxxxxxxx",
    "aws.s3.secret_key" = "yyyyyyyyyy",
    "aws.s3.region" = "us-west-2"
)
SELECT * FROM sales_records;
  • 导出至 HDFS:
INSERT INTO 
FILES(
    "path" = "hdfs://xxx.xx.xxx.xx:9000/unload/data1",
    "format" = "parquet",
    "compression" = "uncompressed",
    "target_max_file_size" = "1024", -- 1KB
    "hadoop.security.authentication" = "simple",
    "username" = "xxxxx",
    "password" = "xxxxx"
)
SELECT * FROM sales_records;

导出数据到不同路径下的多个文件

您还可以使用 partition_by 属性提取指定列的值,从而将数据文件分别存储到不同路径中。

以下示例将 sales_records 中的所有数据行导出为多个 Parquet 文件,存储在路径 /unload/partitioned/ 下。这些文件存储在不同的子路径中,这些子路径根据列 sales_time 中的值来区分。

  • 导出至 S3:
INSERT INTO 
FILES(
    "path" = "s3://mybucket/unload/partitioned/",
    "format" = "parquet",
    "compression" = "lz4",
    "partition_by" = "sales_time",
    "aws.s3.access_key" = "xxxxxxxxxx",
    "aws.s3.secret_key" = "yyyyyyyyyy",
    "aws.s3.region" = "us-west-2"
)
SELECT * FROM sales_records;
  • 导出至 HDFS:
INSERT INTO 
FILES(
    "path" = "hdfs://xxx.xx.xxx.xx:9000/unload/partitioned/",
    "format" = "parquet",
    "compression" = "lz4",
    "partition_by" = "sales_time",
    "hadoop.security.authentication" = "simple",
    "username" = "xxxxx",
    "password" = "xxxxx"
)
SELECT * FROM sales_records;

导出数据到单个文件

要将数据导出到单个数据文件,您必须将 single 属性设置为 true

以下示例将 sales_records 中的所有数据行导出为以 data2 为前缀的单个 Parquet 文件。

  • 导出至 S3:
INSERT INTO 
FILES(
    "path" = "s3://mybucket/unload/data2",
    "format" = "parquet",
    "compression" = "lz4",
    "single" = "true",
    "aws.s3.access_key" = "xxxxxxxxxx",
    "aws.s3.secret_key" = "yyyyyyyyyy",
    "aws.s3.region" = "us-west-2"
)
SELECT * FROM sales_records;
  • 导出至 HDFS:
INSERT INTO 
FILES(
    "path" = "hdfs://xxx.xx.xxx.xx:9000/unload/data2",
    "format" = "parquet",
    "compression" = "lz4",
    "single" = "true",
    "hadoop.security.authentication" = "simple",
    "username" = "xxxxx",
    "password" = "xxxxx"
)
SELECT * FROM sales_records;

导出至 MinIO

用于 MinIO 导出的参数与用于 AWS S3 导出的参数不同。

INSERT INTO 
FILES(
    "path" = "s3://huditest/unload/data3",
    "format" = "parquet",
    "compression" = "zstd",
    "single" = "true",
    "aws.s3.access_key" = "xxxxxxxxxx",
    "aws.s3.secret_key" = "yyyyyyyyyy",
    "aws.s3.region" = "us-west-2",
    "aws.s3.use_instance_profile" = "false",
    "aws.s3.enable_ssl" = "false",
    "aws.s3.enable_path_style_access" = "true",
    "aws.s3.endpoint" = "http://minio:9000"
)
SELECT * FROM sales_records;

使用 NFS 导出到本地文件

如需通过 file:// 协议访问 NFS 中的文件,需要将同一 NAS 设备作为 NFS 挂载到每个 BE 或 CN 节点的相同目录下。

-- 导出为 CSV 文件。
INSERT INTO FILES(
  'path' = 'file:///home/ubuntu/csvfile/', 
  'format' = 'csv', 
  'csv.column_separator' = ',', 
  'csv.row_delimitor' = '\n'
)
SELECT * FROM sales_records;

-- 导出为 Parquet 文件,并将 Parquet 版本设置为 1.0。
INSERT INTO FILES(
  'path' = 'file:///home/ubuntu/parquetfile/',
  'format' = 'parquet',
  'parquet.version' = '1.0'
)
SELECT * FROM sales_records;

5、starrocks导出数据为XML文件

StarRocks本身并不直接支持将数据导出为XML格式,但可以通过以下方法实现:


方法 1:导出为CSV后转换为XML

  1. 使用StarRocks的EXPORT功能导出数据为CSV文件

    1. 使用 EXPORT 语句将数据导出到支持的存储系统(如HDFS、S3等)。

    2. 示例语法:

    EXPORT TABLE your_table
    TO "s3://your-bucket/your-folder/"
    PROPERTIES (
        "format" = "csv",
        "column_separator" = ","
    );
    
    1. 详细配置请参考官方文档。
  2. 使用脚本将CSV转换为XML

    1. 使用Python或其他编程语言读取CSV文件并生成XML文件。

    2. 示例Python代码:

    import csv
    import xml.etree.ElementTree as ET
    
    def csv_to_xml(csv_file, xml_file):
        with open(csv_file, 'r') as f:
            reader = csv.DictReader(f)
            root = ET.Element("root")
            for row in reader:
                item = ET.SubElement(root, "row")
                for key, value in row.items():
                    ET.SubElement(item, key).text = value
            tree = ET.ElementTree(root)
            tree.write(xml_file, encoding="utf-8", xml_declaration=True)
    
    csv_to_xml("data.csv", "data.xml")
    

方法 2:通过INSERT INTO FILES功能

  1. 导出数据到本地文件

    1. 使用 INSERT INTO FILES 功能,支持自定义文件格式。

    2. 示例语法:

    INSERT INTO FILE "file:///path/to/output.csv"
    FORMAT AS CSV
    PROPERTIES (
        "column_separator" = ","
    )
    SELECT * FROM your_table;
    
  2. 转换为XML

    1. 同样使用脚本或工具将生成的CSV文件转换为XML。

方法 3:自定义导出逻辑

如果需要直接生成XML文件,可以通过StarRocks的客户端程序(如JDBC)查询数据并在应用程序中直接生成XML文件。

示例代码(Java):

import java.sql.*;
import java.io.FileWriter;

public class ExportToXML {
    public static void main(String[] args) throws Exception {
        String url = "jdbc:mysql://your-starrocks-host:port/your_database";
        String user = "your_user";
        String password = "your_password";

        Connection conn = DriverManager.getConnection(url, user, password);
        Statement stmt = conn.createStatement();
        ResultSet rs = stmt.executeQuery("SELECT * FROM your_table");

        FileWriter writer = new FileWriter("data.xml");
        writer.write("<root>\n");
        while (rs.next()) {
            writer.write("  <row>\n");
            for (int i = 1; i <= rs.getMetaData().getColumnCount(); i++) {
                String columnName = rs.getMetaData().getColumnName(i);
                String value = rs.getString(i);
                writer.write("    <" + columnName + ">" + value + "</" + columnName + ">\n");
            }
            writer.write("  </row>\n");
        }
        writer.write("</root>");
        writer.close();

        rs.close();
        stmt.close();
        conn.close();
    }
}
posted @ 2025-08-20 16:19  WonderfulDom  阅读(115)  评论(0)    收藏  举报