问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

Rust语言中duckdb和polars库读取CSV文件性能对比

创作时间:
作者:
@小白创作中心

Rust语言中duckdb和polars库读取CSV文件性能对比

引用
CSDN
1.
https://blog.csdn.net/wowotuo/article/details/139987522

在数据分析领域,Rust语言的两个重要库duckdb和polars在处理CSV文件时表现如何?本文通过实际代码和性能测试,对比了这两个库在读取不同大小CSV文件时的效率,帮助开发者选择更适合的工具。

一、实验准备

CSV文件准备

本次实验使用了两个CSV文件,结构相同,均为9列,但行数不同:

  • test.csv:约2.1万行
  • test2.csv:约64万行

CSV文件的具体内容如下:

依赖配置

实验环境基于Rust,使用Cargo管理依赖。具体依赖配置如下:

[package]
name = "my_duckdb"
version = "0.1.0"
edition = "2021"

[dependencies]
duckdb = { version = "0.10.2", features = ["bundled"] }
polars = { version = "0.26.1", features = ["lazy"] }

二、代码实现

主程序(main.rs)

实验中使用了duckdb和polars两种库来读取CSV文件。polars库提供了两种模式:lazy(延迟)和eager(即时)。通常情况下,lazy模式效率更高。

use duckdb::{
    arrow::{record_batch::RecordBatch, util::pretty::print_batches},
    Connection, Result,
};
use polars::prelude::*;
use std::time::Instant;
use std::fs::File;

fn main() {
    let time0 = Instant::now();
    let csvs = ["test.csv", "test2.csv"];
    for csv in csvs {
        println!("-----------{:?}-------------", csv);
        duckdb_read_csv(csv).unwrap();
        polars_eager_read_csv(csv);
        polars_lazy_read_csv(csv);
        println!("-----------{:?}-------------", csv);
    }
    println!("duckdb和polars读文件共花:{:?}秒!", time0.elapsed().as_secs_f32());
}

fn duckdb_read_csv(filepath: &str) -> Result<()> {
    let duckdb_csv_time = Instant::now();
    let db = Connection::open_in_memory()?;
    let sql_format = format!("SELECT * from read_csv('{}');", filepath);
    let rbs: Vec<RecordBatch> = db
        .prepare(&sql_format)?
        .query_arrow([])?
        .collect();
    assert!(rbs.len() > 0);
    println!("duckdb取出的行数:{:?} 列数:{:?}", rbs[0].num_rows(), rbs[0].num_columns());
    println!("duckdb 读csv花时: {:?} 秒!", duckdb_csv_time.elapsed().as_secs_f32());
    let _ = db.close();
    Ok(())
}

fn polars_eager_read_csv(filepath: &str) {
    let polars_eager_csv_time = Instant::now();
    let df = CsvReader::from_path(filepath)
        .unwrap()
        .has_header(true)
        .finish()
        .unwrap();
    println!("polars eager 读出csv的行和列数:{:?}", df.shape());
    println!("polars eager 读csv 花时: {:?} 秒!", polars_eager_csv_time.elapsed().as_secs_f32());
}

fn polars_lazy_read_csv(filepath: &str) {
    let polars_lazy_csv_time = Instant::now();
    let p = LazyCsvReader::new(filepath)
        .has_header(true)
        .finish()
        .unwrap();
    let mut df = p.collect().expect("error to dataframe!");
    println!("polars lazy 读出csv的行和列数:{:?}", df.shape());
    println!("polars lazy 读csv 花时: {:?} 秒!", polars_lazy_csv_time.elapsed().as_secs_f32());
    polars_write_csv(&mut df, &format!("polars_{}", filepath));
}

fn polars_write_csv(df: &mut DataFrame, pathfile: &str) {
    let polars_write_csv_time = Instant::now();
    let mut file = File::create(pathfile).expect("could not create file");
    CsvWriter::new(&mut file)
        .has_header(true)
        .with_delimiter(b' ')
        .finish(df)
        .expect("error!");
    println!("polars write csv 花时: {:?} 秒!", polars_write_csv_time.elapsed().as_secs_f32());
}

三、实验结果

运行上述代码后,得到以下输出结果:

-----------"test.csv"-------------
duckdb取出的行数:2048 列数:9
duckdb 读csv花时: 0.03224426 秒!
polars eager 读出csv的行和列数:(21357, 9)
polars eager 读csv 花时: 0.007638709 秒!
polars lazy 读出csv的行和列数:(21357, 9)
polars lazy 读csv 花时: 0.002562615 秒!
polars write csv 花时: 0.004541633 秒!
-----------"test.csv"-------------
-----------"test2.csv"-------------
duckdb取出的行数:2048 列数:9
duckdb 读csv花时: 0.14970613 秒!
polars eager 读出csv的行和列数:(640710, 9)
polars eager 读csv 花时: 0.026194088 秒!
polars lazy 读出csv的行和列数:(640710, 9)
polars lazy 读csv 花时: 0.020053046 秒!
polars write csv 花时: 0.06960724 秒!
-----------"test2.csv"-------------
duckdb和polars读文件共花:0.31616783秒!

四、结论

  1. 从实验结果来看,在读取CSV文件时,polars库的表现优于duckdb库。
  2. polars库的lazy模式在读取效率上优于eager模式。
  3. polars库在写入CSV文件时也表现出不错的效率。

五、问题与建议

在实验过程中发现,duckdb库读取CSV文件时返回的行数存在异常(显示为2048行,实际应为数万行)。这个问题可能与库的封装有关,建议进一步查实。此外,测试样本量相对较小,建议在更大规模的数据集上进行测试以获得更全面的结论。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号