---
url: /duckdb/csv-big.md
description: DuckDB百亿级数据量性能测试，使用DuckDB分析超百亿数据量
---

# DuckDB百亿级数据性能测试

前面有说过，DuckDB的创建者一开始就放弃了分布式，然后就有同学提出质疑，DuckDB会有性能瓶颈。我只想说，目前DuckDB可以说是单机场景下大数据量分析的最佳选择。

本文，我将为同学们演示DuckDB在百亿级数据量下的性能表现，我感觉我已经彻底魔怔了，百亿级数据量意味着什么？

## 百亿级数据是多少

我们假设一家企业每天可以产生1000万的数据量，那么产生100亿的数据量就需要1000天（超过两年半）。

我们按照前文3亿数据量，CSV文件约9GB，那么100亿就是300G。这个数据量我相信这个世界上已经没有几个单机可以处理这个CSV文件了。

此情此景，如何解决呢？

答案就是Parquet。

## Parquet是什么

Parquet又称Apache Parquet，是Apache Hadoop生态系统的一种免费、开源的面向列的数据存储格式。

**Parquet优点**

* 数据压缩

* 列式存储

* 与编程语言无关

* 开源格式，免费使用

* 支持复杂数据类型

## 创建超百亿的数据量

1. 创建数据库文件并创建表

```sql
CREATE TABLE weather (
    city    VARCHAR,
    temp_lo INTEGER,
    temp_hi INTEGER,
    prcp    REAL,
    date    DATE
);
```

![](/img/45e0ab09-827e-49ca-be69-7a056d9217ca.png)

2. 插入数据

```sql
INSERT INTO main.weather
VALUES ('San Francisco', 46, 50, 0.25, '1994-11-27');
```

![](/img/0fedf593-020d-47a2-900e-7df226679984.png)

3. 反复插入数据，使单表数据量达到上亿级别

```sql
INSERT INTO main.weather
select * from main.weather;
```

![](/img/e5ce595d-7c1c-4855-8959-637f547268c2.png)

重复执行SQL，单表数据量会达到上40亿级别。

数据量超40亿之后再使用该方式可能会提示内存不足，所以我们再优化一下

```sql
INSERT INTO main.weather
select * from main.weather limit 500000000;
```

每次我们只插入5亿条数据，重复插入，知道达到超过100亿。
![](/img/af4f1c7f-cd0c-4ea3-8d30-ef98038d28a7.png)

4. 确认单表数据量

```sql
select count(*) from main.weather;
```

![](/img/dd1d536d-dd1f-4f2d-afd1-3bbb88fd3a20.png)

这边百亿只超过了1条，调皮一下下。

5. 测试内部表查询性能

```sql
select city, count(*), sum(temp_lo), sum(temp_hi) from main.weather
group by city;
```

![](/img/d8f9f1ba-5a06-4018-a951-505bf5958169.png)

耗时约34s，你是否能接受呢。

6. 导出为Parquet格式

```sql
copy main.weather to 'E:\duckdbtest\weather.parquet' (format 'parquet');
```

由于导出时间过长，则先导出1亿数据量，然后通过复制的方式得到100份含有一亿数据量的文件。

```sql
copy (select * from main.weather limit 100000000) to 'E:\duckdbtest\weather.parquet' (format 'parquet');
```

![](/img/9e6bd352-c779-48d1-bfac-e662266bd5dc.png)

![](/img/8c009fc0-2822-484e-ad6b-278922253ae6.png)

7. 验证数据量

```sql
select count(*) from 'E:\duckdbtest\*.parquet';
```

![](/img/4560be14-a3cb-49f2-b983-07a5058460bf.png)
通过正则匹配的方式，可以把多个文件里的数据合并读取，这也是DuckDB更灵活的特点。

分组聚合

```sql
select city, sum(temp_lo), sum(temp_hi) from 'E:\duckdbtest\*.parquet'
group by city;
```

![](/img/e881012a-4493-461c-ba0e-593583952f77.png)

耗时约4min。

总结，Parquet相比CSV可以节省大量的存储空间，查询性能也更好，100亿数据量4min内完成聚合计算，表现还是相当可以的。但是性能最好的还是DuckDB的内部表，可以把数据读出数据后保存到内部表后再做分析。

```sql
create table weater_parquet as
select * from 'E:\duckdbtest\*.parquet'; 
```

如果一次写入太慢，可以考虑分批写入。

## 进阶

在日常处理数据过程中，对于中间数据过程可以尝试使用占用空间更少的Parquet格式，同时Parquet文件也可以用于Hive等其它大数据产品中。针对复杂的分析需求，可以使用数仓开发的分层思维，一层层做聚合，使得开发效果达到最高。想要学习DuckDB更多玩法，请关注：遇码，回复**duckdb**，获取官方文档。
