DuckDB-源码分析(2)Parquet读设计

在ParquetReader的构造函数中,会打开文件句柄,加载元数据,并初始化。Scan函数负责实际的扫描过程,处理行组,应用过滤器,读取数据到DataChunk中。首先,在元数据加载部分,parquet文件的元数据通常位于文件末尾,包含schema、行组信息、统计信息等。LoadMetadata函数通过读取文件末尾的元数据部分,解析出FileMetaData结构。

DeriveLogicalType函数根据Parquet的SchemaElement中的类型信息(如Type、converted_type、logicalType)转换为DuckDB的LogicalType。例如,Parquet的INT32可能对应DuckDB的INTEGER,而带有converted_type为DATE的INT32会被转换为DATE类型。这里还处理了时间戳、UUID等复杂类型的转换。

创建列读取器的过程在CreateReaderRecursive中完成,这个函数递归地遍历SchemaElement树,根据每个元素的类型和子元素创建相应的ColumnReader。例如,遇到STRUCT类型时,会创建StructColumnReader,并为每个子列创建对应的读取器,对于重复的字段(如LIST或MAP),会使用ListColumnReader来处理嵌套结构。

初始化时,InitializeSchema调用CreateReader创建根读取器,通常是StructColumnReader,因为它对应Parquet文件的根结构。然后根据读取到的列信息填充columns向量,记录每个列的名称和类型。

扫描数据的过程由Scan函数处理。ParquetReaderScanState用于跟踪扫描的状态,包括当前处理的行组、文件句柄、过滤器等。PrepareRowGroupBuffer函数准备当前行组的数据,可能应用统计信息进行过滤,跳过不需要读取的行组。然后通过ColumnReader的Read方法将数据读取到DataChunk中,应用过滤器(如果有的话),最终将结果返回。

过滤器处理部分,ApplyFilter函数根据过滤条件对读取的数据进行过滤。例如,等值比较、范围比较、IS NULL等条件会被应用到数据上,减少需要处理的数据量,提升查询性能。

阅读更多

DuckDB-源码分析(1)背景与应用

2019年,CWI发表了一篇关于DuckDB的论文:《DuckDB: an Embeddable Analytical Database》,旨在OLAP领域构建一个嵌入式的数据库,解决单点交互式数据分析的问题,并给边缘计算提供除SQLite之外的更优选择。在论文中,作者们总结DuckDB为在一个进程内的SQL OLAP DBMS,这句话至少有两个解读点:

  1. DuckDB的工作方式应该和SQLite一致,即在进程内部运行,并不需要类似MySQL或者PG的等单独起一个数据库服务;
  2. 作为AP系统,可以支撑一定复杂的数据分析和查询任务。

SQLite是在全球运行最多的关系型数据库管理系统,每个浏览器和操作系统以及各种嵌入式设备都能找到该数据库使用的痕迹。但是SQLite更多为TP任务服务,很难利用向量化、内存加速来提高数据分析的速度。所以DuckDB弥补了SQLite这方面的空白。

阅读更多
Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×