iT邦幫忙

2026 iThome 鐵人賽

DAY 7
1
Software Development

1+1+1>3 ~ Spark 與 DataFusion、Comet 效能煉金術 ~系列 第 7

Day 07 DataFusion 是函式庫,datafusion-cli 是外殼

  • 分享至 

  • xImage
  •  

今天原本想說來做個實驗,但需要先來介紹個 DataFusion
因為明天要來測量 SortExec,那今天先把工具介紹一下

SQL 是宣告式

提到 Database system 就必須簡單說明一下會用到的語言,也就是鼎鼎大名的SQL

SQL(Structured Query Language)他是用來描述需要哪些資料
只說要哪些欄、做什麼事;迴圈怎麼掃、排序用哪種演算法,交給引擎
這就是 declarative 宣告式

例如:

SELECT id, g FROM t WHERE g > 50 ORDER BY g;

沒指定用哪種排序、一批幾列,根本不需要管那些,因為那些是 DataFusion 要處理的事。
若改成寫 for 迴圈掃檔、比較、再排,那就是 imperative 命令式——步驟你全包辦。

DataFusion 是函式庫,CLI 只是外殼

DataFusion 是用 Rust 寫的查詢引擎:把那句 SQL 讀懂、規劃出執行步驟、然後拿去算。

datafusion-cli,只是換一個入口:同一個函式庫,外面加了讀檔、畫表格、等到看到分號才送出。
底下跑的還是 Arrow 的 RecordBatch,跟前幾天講的一批一批是同一件事。

https://ithelp.ithome.com.tw/upload/images/20260823/20183544pQPoNm9SMb.png

一句 SQL 怎麼變成會跑的計劃

引擎不是拿到字串就開始掃資料
中間還有兩層計劃:邏輯計劃說「做什麼」,實體計劃才說「用哪個算式做」。
後面 EXPLAIN 印出來的那棵樹,就是右邊那格實體計劃,最頂的 SortExec 先記著,明天的實驗就在那。

安裝

  • macOS(Homebrew):brew install datafusion
  • 有 Rust 環境:cargo install datafusion-cli
  • 用 docker 安裝:docker run -it --rm apache/datafusion-cli

裝好打 datafusion-cli 進到互動介面,看到 > 提示字元就對了

$ datafusion-cli
DataFusion CLI v54.1.0
>

datafusion-cli 用法

進到互動介面後,指令分兩個塊:

  • SQL:一定要 ; 結尾才會送出,少打分號 CLI 會一路等下一行,直到看到 ; 為止(Oracle SQL*Plus 用 / 觸發跑緩衝區,這裡沒這東西,/ 只會被當成下一句的開頭卡在那)
  • CLI meta command:反斜線開頭,不用分號,Enter 就跑

常用的幾個:

指令 做什麼
\? 列出全部 meta command
\d 列出目前有哪些表
\d 表名 看某張表的欄位
\q 離開(或按 Ctrl+D

想改引擎行為,用 SET

SET datafusion.execution.batch_size = 4096;
SHOW ALL;                                  -- 看目前全部 config
SHOW datafusion.execution.batch_size;      -- 只看某一項

SET / SHOW 也算 SQL,結尾一樣要 ;

一次餵一個檔案的 SQL,啟動時加 -f

datafusion-cli -f script.sql

SQL 子句的書寫順序是固定的,寫錯 parser 直接擋下,不會幫你調:

WITH … SELECT … FROM … JOIN … WHERE … GROUP BY … HAVING … ORDER BY … LIMIT … OFFSET

但執行順序不一樣,大致是 FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT。SELECT 排在 WHERE 之後,所以 SELECT 裡取的別名在 WHERE 用不到,在 ORDER BY 卻可以。

小小實作

先弄一筆假資料玩玩,直接用 VALUES 造一張表:

CREATE TABLE demo AS
SELECT * FROM (VALUES
    (1, 'a', 10.0),
    (2, 'b', 20.0),
    (3, 'c', 30.0),
    (4, 'd', 40.0)
) AS t(id, name, price);

跑個 SELECT 確認資料在了:

SELECT * FROM demo WHERE price > 15;

會輸出

> SELECT * FROM demo WHERE price > 15;
+----+------+-------+
| id | name | price |
+----+------+-------+
| 2  | b    | 20.0  |
| 3  | c    | 30.0  |
| 4  | d    | 40.0  |
+----+------+-------+
3 row(s) fetched. 
Elapsed 0.013 seconds.

也可以直接讀本地檔案,Parquet、CSV、JSON 都吃:

SELECT * FROM 'data.parquet' LIMIT 5;

想看引擎怎麼規劃這句 SQL,加 EXPLAIN,印出來的就是上面那張圖裡的實體計劃:

EXPLAIN SELECT * FROM demo ORDER BY price DESC;

會吐出一棵 plan tree,長得像這樣:

> EXPLAIN SELECT * FROM demo ORDER BY price DESC;
+---------------+-------------------------------+
| plan_type     | plan                          |
+---------------+-------------------------------+
| physical_plan | ┌───────────────────────────┐ |
|               | │          SortExec         │ |
|               | │    --------------------   │ |
|               | │        price@2 DESC       │ |
|               | └─────────────┬─────────────┘ |
|               | ┌─────────────┴─────────────┐ |
|               | │       DataSourceExec      │ |
|               | │    --------------------   │ |
|               | │        bytes: 1432        │ |
|               | │       format: memory      │ |
|               | │          rows: 1          │ |
|               | └───────────────────────────┘ |
|               |                               |
+---------------+-------------------------------+
1 row(s) fetched. 
Elapsed 0.004 seconds.

最頂那個 SortExec 就是明天要做的實驗,多欄排序為什麼比單欄貴這麼多,答案就在這裡

那就明天見~


上一篇
Day 06 效能底層煉金:從 Clang 組合語言拆解 Arrow 記憶體與向量化
下一篇
Day 08 DataFusion SortExec:多欄 ORDER BY 為什麼比單欄貴
系列文
1+1+1>3 ~ Spark 與 DataFusion、Comet 效能煉金術 ~21
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言