找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

314

积分

0

好友

40

主题
发表于 7 天前 | 查看: 16| 回复: 0

本文将通过一个完整的实例,演示如何在 IoTDB 2.0.x (以2.0.6版本为例) 中对表模型进行数据写入,并通过自定义工具分析底层TsFile文件结构,帮助开发者深入理解IoTDB的数据存储机制。

一、生成测试SQL文件

为了批量写入数据,我们首先编写一个Python脚本,用于生成包含建表、插入数据的SQL文件。这种方法在需要进行数据库操作的性能测试或功能验证时非常高效。

import random

# 创建数据库和表
sql1 = "create database demo_test;\n"
sql2 = "use demo_test;\n"
# 注意:时间戳列可以省略
sql3 = "CREATE TABLE t1(id INT FIELD, gauss_val FLOAT FIELD, uniform_val INT FIELD, district STRING FIELD);\n"

with open('test_sql.txt', 'w', encoding='utf-8') as f:
    f.write(sql1)
    f.write(sql2)
    f.write(sql3)

    # 插入数据
    test_point_num = 32000
    for i in range(test_point_num):
        gauss_val = random.gauss(0, 1) * 100 + 300
        uniform_val = (int) (random.random() * 100)
        # 注意时间戳
        sql = f"INSERT INTO t1 VALUES ({i+1}, {i + 1}, {gauss_val:.3f}, {uniform_val}, 'district_{i%10}');\n"
        f.write(sql)

    # 刷盘
    f.write("FLUSH;\n")

执行上述Python脚本后,生成的test_sql.txt文件前几行内容如下:

create database demo_test;
use demo_test;
CREATE TABLE t1(id INT32 FIELD, gauss_val FLOAT FIELD, uniform_val INT32 FIELD, district STRING FIELD);
INSERT INTO t1 VALUES (1, 1, 424.288, 61, 'district_0');
INSERT INTO t1 VALUES (2, 2, 227.418, 5, 'district_1');

二、控制TsFile中Page的点数

IoTDB的TsFile文件是数据存储的核心。默认情况下,一个Page(数据页)包含多达1万个数据点(前提是页面大小未超过64KB)。过多的点数可能会影响基于统计数据的过滤性能。我们可以通过SQL的SET命令动态调整每个Page存储的最大点数。

将以下语句添加到test_sql.txt文件的第一行:

set configuration "max_number_of_points_in_page" = '1000';

需要注意的是,如果通过源码方式(运行ConfigNode.javaDataNode.java)启动IoTDB服务,可能会因为配置文件路径问题导致SET命令执行报错(错误信息通常提示找不到iotdb-system.properties文件)。

IoTDB CLI配置命令执行报错

不过,即使报错也无需担心。因为max_number_of_points_in_page是热加载参数,IoTDB服务进程已经将其值临时修改为1000,只是未能写入配置文件持久化。后续我们将通过分析工具验证这一修改是否生效。

三、编写自定义客户端MyCLi

直接使用IoTDB CLI逐条执行SQL速度较慢。为了提高效率,我们可以基于其代码编写一个自定义客户端MyCli.java,用于自动读取并执行整个SQL文件。

package org.apache.iotdb.cli;

// ... 导入包(此处省略,保留关键代码结构)

/**
 * MyCli - 自动执行SQL文件的客户端
 * args[]: -h 127.0.0.1 -p 6667 -u root -pw root -f /path/to/sql/file.txt
 */
public class MyCli extends AbstractCli {
    private static CommandLine commandLine;
    private static final Properties info = new Properties();

    // 新增文件参数
    private static final String FILE_ARGS = "f";
    private static final String FILE_NAME = "file";
    private static final String FILE_ARGS_LONG = "file";

    /**
     * MyCli主函数
     */
    public static void main(String[] args) throws ClassNotFoundException, IOException {
        runMyCli(new CliContext(System.in, System.out, System.err, ExitType.SYSTEM_EXIT), args);
    }

    public static void runMyCli(CliContext ctx, String[] args)
            throws ClassNotFoundException, IOException {
        // ... 参数解析、连接数据库等逻辑
        // 核心功能:读取并执行指定文件中的所有SQL语句
        executeSqlFile(ctx, filePath);
    }

    /**
     * 执行SQL文件中的所有SQL语句
     */
    private static void executeSqlFile(CliContext ctx, String filePath) {
        // ... 文件检查、读取SQL、建立连接
        // 循环执行所有SQL语句
        executeAllSqlStatements(ctx, connection, sqlStatements);
    }

    // ... 其他辅助方法(读取文件、执行单条SQL等)
}

代码较长,此处仅展示关键结构和注释,完整实现需参考原文或自行补充。

运行MyCli.java前,需要在IDE中配置运行参数,至少包含-u root -pw root -sql_dialect table,以指定用户名、密码和使用表模型。启动后,程序会提示输入SQL文件路径,输入test_sql.txt即可开始自动执行。

MyCli运行配置界面

程序会逐条显示SQL执行状态,正常情况下所有语句都会执行成功。

四、执行SQL查询验证数据

数据写入后,我们可以启动标准的Cli.java进行查询验证。执行以下查询语句:

select * from demo_test.t1 where time between 1998 and 2002;

IoTDB CLI查询结果展示

为了分析查询的执行细节,可以使用explain analyze命令:

explain analyze select * from demo_test.t1 where time between 1998 and 2002;

SQL执行计划分析结果

从分析结果可以看到,DeviceTableScanNode在读取文件时,其Next函数被调用了两次,这可能是由于加载了两个Page的数据所致,与之前设置的Page点数上限(1000)和查询的时间范围是吻合的。

五、分析生成的TsFile文件

MyCli执行完成后,数据会持久化到TsFile中。在项目目录的data文件夹下可以找到生成的.tsfile文件。由于我们插入的数据时间戳是有序的,因此只会生成顺序文件(无序数据会同时产生顺序文件和乱序文件)。

项目数据目录中的TsFile文件

为了深入理解存储结构,我们可以使用IoTDB自带的TsFileSketchTool工具分析文件。为了方便,可以直接修改其main方法中的文件路径参数并运行。

public class TsFileSketchTool {
  public static void main(String[] args) throws IOException {
    // 注释掉原有的参数检查,直接指定文件路径
    String filename = "./data/datanode/data/sequence/demo_test/26/0/1765198758289-1-0-0.tsfile";
    String outFile = "ts_file_sketch.txt";
    System.out.println("TsFile path:" + filename);
    System.out.println("Sketch save path:" + outFile);
    new TsFileSketchTool(filename, outFile).run();
  }
}

运行该工具后,会输出详细的文件结构信息。通过分析输出,我们可以验证之前的操作效果,这对进行大数据存储性能调优很有帮助:

  1. 列与Chunk:表t1有5个列(包含隐式的时间戳列),每个列对应一个Chunk。
  2. Page分割:每个Chunk下包含多个Page。例如id列被分成了32个Page,每个Page恰好存储1000个数据点,这证实了set configuration "max_number_of_points_in_page" = '1000';设置已生效。
  3. 统计信息:每个Page都存储了该页数据的最小值、最大值、开始时间、结束时间等统计信息,即使是STRING类型的district列也是如此。这些统计信息用于查询时的快速过滤。
TsFile path:./data/datanode/data/sequence/demo_test/26/0/1765198758289-1-0-0.tsfile
Sketch save path:ts_file_sketch.txt
-------------------------------- TsFile Sketch --------------------------------
file path: ./data/datanode/data/sequence/demo_test/26/0/1765198758289-1-0-0.tsfile
file length: 178058
...
||||||||||||||||||||| [Chunk Group] of t1, num of Chunks:5
...
                  12|   [Chunk] of t1.id, startTime: 1 endTime: 32000 count: 32000 [minValue:1,maxValue:32000,firstValue:1,lastValue:32000,sumValue:512016000]
                    |       [chunk header] marker=65, measurementID=id, dataSize=3455, dataType=INT32, compressionType=LZ4, encodingType=TS_2DIFF
                    |       [page-1]  UncompressedSize:257, CompressedSize:62, startTime: 1 endTime: 1000 count: 1000 [minValue:1,maxValue:1000,firstValue:1,lastValue:1000,sumValue:500500]
                    |       [page-2]  UncompressedSize:257, CompressedSize:63, startTime: 1001 endTime: 2000 count: 1000 [minValue:1001,maxValue:2000,firstValue:1001,lastValue:2000,sumValue:1500500]
                    |       ... (共32个Page)
...
---------------------------------- TsFile Sketch End ----------------------------------

通过以上步骤,我们完成了从数据生成、写入、查询验证到存储文件分析的完整流程,有助于开发者深入掌握IoTDB表模型的数据处理与存储原理。




上一篇:Photoshop 1.0源码分析:架构设计与Pascal语言选择揭秘
下一篇:从编码到协作:识别程序员缺乏工程实践的7个关键信号
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2025-12-24 19:22 , Processed in 0.321743 second(s), 40 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2025 云栈社区.

快速回复 返回顶部 返回列表