---
title: Databend 开源周报第 85 期
description: Databend 现在支持在将数据加载到表时进行数据转换。本周的编程角还介绍了并行运行多个 Future 的技巧。
slug: category-weekly/databend-weekly-85
date: 2023-03-20
tags: [weekly]
category: Weekly

image: databend-weekly.png
contributors:
  - name: andylokandy
  - name: ariesdevil
  - name: b41sh
  - name: BohuTANG
  - name: Carlosfengv
  - name: Chasen-Zhang
  - name: dantengsky
  - name: dependabot[bot]
  - name: drmingdrmer
  - name: everpcpc
  - name: jun0315
  - name: leiysky
  - name: lichuang
  - name: mergify[bot]
  - name: PsiACE
  - name: RinChanNOWWW
  - name: soyeric128
  - name: sundy-li
  - name: TCeason
  - name: wubx
  - name: Xuanwo
  - name: xudong963
  - name: youngsofun
  - name: zhang2014
  - name: zhyass
authors:
  - DatabendLabs
---

# Databend 开源周报 第 85 期

> 英文版移步：https://www.databend.com/blog/2023-03-17-databend-weekly
>
> [Databend](https://github.com/databendlabs/databend) 是一款现代云数仓。专为弹性和高效设计，为您的大规模分析需求保驾护航。自由且开源。即刻体验云服务：[https://app.databend.cn](https://app.databend.cn) 。

> :loudspeaker: Databend 不再依赖 max_storage_io_requests 设置进行 IO 预读，我们建议使用 v1.0.17-nightly 之后的版本用户，执行 `unset max_storage_io_requests` 以减少不必要的内存占用。

## What's On In Databend

探索 Databend 本周新进展，遇到更贴近你心意的 Databend。

### Data Type: MAP

MAP 数据结构使用嵌套的 `Array(Tuple(key, value))` 来保存键值对。键必须指定为基本数据类型，并且不允许重复；而值可以是任何数据类型，包括嵌套数组或元组。Databend 还会为 MAP 创建布隆过滤器索引，搜索 MAP 中的值会更加快速。

```sql
select * from nginx_log where log['ip'] = '205.91.162.148';
+----+----------------------------------------+
| id | log                                    |
+----+----------------------------------------+
| 1  | {'ip':'205.91.162.148','url':'test-1'} |
+----+----------------------------------------+
```

如果你想了解更多关于 MAP 数据类型的信息，请阅读以下材料：

- [Docs | Data Types - Map](https://docs.databend.cn/sql/sql-reference/data-types/map)

### Data Transformation During Loading Process

你还记得上周提到的两个 RFC 吗？现在，Databend 已经支持在加载数据到表的过程中进行数据转换。使用 `COPY INTO <table>` 命令即可实现基本的转换操作。

```sql
CREATE TABLE my_table(id int, name string, time date);

COPY INTO my_table
FROM (SELECT t.id, t.name, to_date(t.timestamp) FROM @mystage t)
FILE_FORMAT = (type = parquet) PATTERN='.*parquet';
```

该功能可以避免在临时表中存储预转换数据，并支持列重新排序、列省略和类型转换操作。此外，可以从 Stage 中的 Parquet 文件加载部分数据或者对其列进行重新排列。该功能简化和优化了 ETL 过程，使用户能够更加关注数据分析而不必考虑如何移动他们的数据。

如果你对这一特性感兴趣，可以查阅下面列出的材料：

- [Docs | Transforming Data During a Load](https://docs.databend.cn/guides/load-data/)
- [PR | feat(storage): Map data type support bloom filter](https://github.com/databendlabs/databend/pull/10457)

{/* truncate */}

## Code Corner

一起来探索 Databend 和周边生态中的代码片段或项目。

### Run Multiple Futures Parallel

你对并行运行多个 Future 感兴趣吗？Databend 利用这种方法极大地改善了在大量文件情况下的扫描性能。

下面这段不到 30 行的代码将会揭示如何实现这一技巧。

```rust
/// Run multiple futures parallel
/// using a semaphore to limit the parallelism number, and a specified thread pool to run the futures.
/// It waits for all futures to complete and returns their results.
pub async fn execute_futures_in_parallel<Fut>(
    futures: impl IntoIterator<Item = Fut>,
    thread_nums: usize,
    permit_nums: usize,
    thread_name: String,
) -> Result<Vec<Fut::Output>>
where
    Fut: Future + Send + 'static,
    Fut::Output: Send + 'static,
{
    // 1. build the runtime.
    let semaphore = Semaphore::new(permit_nums);
    let runtime = Arc::new(Runtime::with_worker_threads(
        thread_nums,
        Some(thread_name),
    )?);

    // 2. spawn all the tasks to the runtime with semaphore.
    let join_handlers = runtime.try_spawn_batch(semaphore, futures).await?;

    // 3. get all the result.
    future::try_join_all(join_handlers)
        .await
        .map_err(|e| ErrorCode::Internal(format!("try join all futures failure, {}", e)))
}
```

如果你对这个 Rust 技巧感兴趣，可以阅读这个 PR [feat: improve the parquet get splits to parallel](https://github.com/databendlabs/databend/pull/10514) 。

### How to Create a System Table

系统表用于提供 Databend 内部状态信息，例如表、函数和设置。

如果你对如何创建系统表感兴趣，可以查看我们最近发布的文档，使用 `system.credits` 表作为示例，展示如何实现、注册和测试系统表。

以下是部分代码片段：

```rust
let table_info = TableInfo {
    desc: "'system'.'credits'".to_string(),
    name: "credits".to_string(),
    ident: TableIdent::new(table_id, 0),
    meta: TableMeta {
        schema,
        engine: "SystemCredits".to_string(),
        ..Default::default()
    },
..Default::default()
};
```

- [Docs | How to Create a System Table](https://docs.databend.cn/developer/community/rfcs/new-datavalues-system)

## 亮点

以下是一些值得注意的事件，也许您可以找到感兴趣的内容。

- OpenDAL 项目现已正式移交到 Apache 软件基金会名下，欢迎阅读 [官宣：OpenDAL 成功进入 Apache 孵化器](https://www.databend.cn/blog/apache-opendal-incubating/) 了解更多信息。
- 现在 Databend 可与 MindsDB 无缝集成，从而扩展你的机器学习工作流：[Bringing in-database ML to Databend](https://mindsdb.com/integrations/databend-machine-learning) 。
- 如果你计划使用 WebHDFS 作为 Databend 的存储后端，这篇博客可能提供一些有用的信息 [How to Configure WebHDFS as a Storage Backend for Databend](https://www.databend.com/blog/2023-03-13-webhdfs-storage-for-backend) 。

## What's Up Next

我们始终对前沿技术和创新理念持开放态度，欢迎您加入社区，为 Databend 注入活力。

### Quantile 支持设置多个 Level

> 在 [#10633](https://github.com/databendlabs/databend/pull/10633) 的实现中，已经支持传递多个 levels。但是 Issue 中提出的 `kurtosis(x)` 和 `skewness(x)` 方法也可以视作为 Databend 贡献的一个好的开始。

在 PR [#10474](https://github.com/databendlabs/databend/pull/10474) 合并后，Databend 开始支持 `QUANTILE` 聚合函数，但目前仅支持将单个浮点值设置为 level。如果它还可以支持传递多个参数，或传递列表作为参数，则可能有助于简化某些情况下的 SQL 编写。

```sql=
SELECT QUANTILE([0.25, 0.5, 0.75])(number) FROM numbers(25);
+-------------------------------------+
| quantile([0.25, 0.5, 0.75])(number) |
+-------------------------------------+
|            [6, 12, 18]              |
+-------------------------------------+
```

[Feature: quantile support list and add functions kurtosis() and skewness()](https://github.com/databendlabs/databend/issues/10589)

如果你对这个主题感兴趣，可以尝试解决其中的部分问题或者参与讨论和 PR review。或者，你可以点击 https://link.databend.com/i-m-feeling-lucky 来挑选一个随机问题，祝好运！

## Changelog

前往查看 Databend 每日构建的变更日志，以了解开发的最新动态。

地址：https://github.com/databendlabs/databend/releases
