sql5 3.2.17

SQLite compatible database with CJK FTS5 full-text search
# Query Planner - 查詢規劃理論

`src/planner/planner.rs`

## 查詢規劃的角色

Query Planner 是資料庫系統的核心元件,負責將 SQL 語句轉換為可執行的查詢计划:

```
SQL 字串 → [Parser] → AST → [Planner] → Plan → [Executor] → 結果
```

## 代數優化 (Algebraic Optimization)

### 查詢代數

SQL 可表示為關聯代數運算:

```sql
SELECT name FROM users WHERE age > 18
```

等价於:

```
π_name (σ_age>18 (users))
```

其中:
- π = Projection (選擇欄位)
- σ = Selection (過濾條件)

### 等價變換

相同的結果可能有多種表達:

```sql
σ_{A>5} (R ⨝ S) ≡ R ⨝ σ_{A>5} (S)  -- 條件提前
π_{X} (σ_{A>5} (R)) ≡ σ_{A>5} (π_{X,A} (R))  -- 投影提前
```

## 代價模型 (Cost Model)

評估不同计划的執行代價:

```
Cost = CPU_cost + I/O_cost × weight

典型估計:
- 全表掃描:O(n) 其中 n 為總頁數
- 索引掃描:O(log n) + 範圍頁數
- 巢狀迴圈 Join:O(n × m)
```

## 啟發式優化 (Heuristic Optimization)

本專案採用的簡化策略:

### 1. 條件下推 (Predicate Pushdown)

將過濾條件尽可能下推到資料來源:

```
較差:σ (π (R))          -- 先投影再過濾
較佳:π (σ (R))          -- 先過濾再投影
```

### 2. 主鍵等值 → 索引掃描

```sql
WHERE id = 42  -- 若 id 是主鍵
→ IndexScan(id = 42)  -- 直接索引查找
```

### 3. 其他過濾 → SeqScan + filter

```sql
WHERE name = 'Alice'  -- 非主鍵欄位
→ SeqScan(filter: name = 'Alice')  -- 全表掃描 + 記憶體過濾
```

## 查詢计划的生成流程

```
1. Parse SELECT 語句
2. 處理 FROM:建立基礎掃描
3. 處理 JOIN:追加 Join 節點
4. 處理 WHERE:條件下推或包裝 Filter
5. 處理 GROUP BY:包裝 Aggregate 節點
6. 處理 ORDER BY:包裝 Sort 節點
7. 處理 LIMIT:包裝 Limit 節點
8. 處理投影:包裝 Projection(或在 Aggregate 中處理)
```

## 邏輯計劃 vs 實體計劃

### 邏輯計劃(Logical Plan)

描述「做什麼」,與執行無關:

```
Plan::Aggregate { group_by: [city], ... }
 └─ Plan::SeqScan { table: "users", ... }
```

### 實體計劃(Physical Plan)

描述「如何做」:

```
HashJoin
 ├─ SeqScan(users)
 └─ IndexScan(orders, user_id)
```

## 理論參考

- Selinger et al., "Access Path Selection in a Relational Database Management System" (1979)
- Garcia-Molina, Ullman, Widom, "Database Systems: The Complete Book"
- Ioannidis, "Query Optimization" (ACM Computing Surveys, 1996)