上一篇把 conversation 保存成可以重複執行的 Analysis。
同一個 Analysis 也可以換 datasource 執行,所以可以先用 schema 相同、size 比較小的資料建立 Analysis,上 production 後再換成更大的資料。
但這裡會碰到一個問題:
schema 符合,不代表原本的 execution strategy 還適合。
目前 Analysis Optimization 的 flow 是:
Run
↓
Check
↓
Finding
↓
User clicks Optimize
↓
Rewrite
↓
Candidate Recipe
↓
Validation
↓
New Version
這篇先看前半段:
Check
→ Rewrite
Validation 留到下一篇。
Run Analysis 時,不是直接把 data 搬進 sandbox。
System 會先看一組 execution measurements。
Database 到 Sandbox 這一段會看:
estimated rows
estimated bytes
exported rows
exported bytes
query time
Sandbox 裡則會看:
script time
CPU
peak memory
OOM
其中 Pre-run Check 會先用 PostgreSQL EXPLAIN,在真正執行 query 之前估算:
Plan Rows
Plan Width
↓
Estimated Rows
Estimated Bytes
EXPLAIN 不會真的讀完整份 data,也不會 export rows,所以這個 check 很便宜。
如果 estimate 沒超過 hard limit,就繼續正常執行。
例如同一個 Analysis 跑在原本建立它的小 datasource:
Estimated rows ~10,790
Actual rows 10,714
Export size 100 KB
Script time 1.6s
Peak memory 210 MB
全部都在 limit 內,所以不需要 optimization。

但換到比較大的 events_enterprise:
Estimated rows
→ ~4.2M
Hard limit
→ 100K
Pre-run Check 就會直接停止。
這時:
沒有 export data
沒有啟動 sandbox
UI 會顯示:
The saved strategy no longer fits events_enterprise
並讓 user 決定要不要按 Optimize。

超過 limit 之後,也不是直接叫 Agent 自己猜問題。
System 會先用固定規則把 finding 分類:
data_movement
→ DB → Sandbox 的資料太多
→ rewrite SQL
sandbox_memory
→ input 不大,但 script memory 太高 / OOM
→ rewrite script
sandbox_runtime
→ input 不大,但 script 太慢
→ rewrite script
這些判斷都是 deterministic rule。
只有真正要改 SQL / script 的時候,才交給 Agent。
所以:
Measurement
↓
Finding
↓
Rewrite Direction
先由 system 決定。
Check 發現問題後,不會自動改 Analysis。
目前採用的是 ask first:
Check
→ Stop / Recommend
→ Show Reason
→ User clicks Optimize
因為 Optimize 會使用 model,也可能產生新的 Analysis version。
User 按下 Optimize 後,server 才會組出 Optimization Request。
Agent 會拿到:
Analysis
→ question
→ current recipe
→ outputs
Target
→ selected datasource
Evidence
→ estimate / measurement
→ limits
→ finding
Goal
→ 要解決哪個 bottleneck
所以 Agent 不是重新從零猜怎麼 optimize,而是根據實際 measurement rewrite。
例如另一個 Analysis:
計算過去 30 天,不同 device type 的 median session length。
原本做法是:
raw events
→ Sandbox
→ Python calculates sessions
→ median
當 datasource 變大後,finding 是:
data_movement
所以 rewrite goal 會要求把 reduction 往 PostgreSQL 推。
原本:
SELECT
event_id,
user_id,
session_id,
device_type,
event_type,
event_time
FROM events
WHERE event_time >= NOW() - INTERVAL '30 days'
rewrite 後變成:
SELECT
device_type,
ROUND(
CAST(
percentile_cont(0.5)
WITHIN GROUP (ORDER BY session_minutes)
AS numeric
),
4
) AS median_session_min,
COUNT(*) AS n_sessions
FROM (
SELECT
session_id,
device_type,
EXTRACT(EPOCH FROM (MAX(event_time) - MIN(event_time))) / 60.0
AS session_minutes
FROM events
WHERE event_time >= NOW() - INTERVAL '30 days'
GROUP BY session_id, device_type
) sessions
GROUP BY device_type
ORDER BY median_session_min DESC;
execution strategy 從:
raw rows
→ Sandbox
→ Python aggregate
變成:
raw rows stay in PostgreSQL
→ aggregate
→ few rows
→ Sandbox
→ report
這次 optimization 改的不是 Analysis 要回答什麼,而是:
computation 在哪一層完成。
Agent 最後會產生一份新的 candidate recipe。
Current Analysis
↓
Check
↓
Finding
↓
User clicks Optimize
↓
Agent rewrites
↓
Candidate Recipe
但 candidate 還不能直接變成新的 version。
因為還有最後一個問題:
新的 recipe 雖然更有效率,但怎麼確認它沒有改變原本的計算結果?
這就是下一篇要處理的:
Validation
→ rewritten Analysis still means the same thing?