什么时候向量化会"失效" ⚠️ 以下场景会降低向量化优势:
1️⃣ 复杂 UDF / lambda
2️⃣ 每行逻辑分支非常复杂
3️⃣ 极端小数据量(几十行)
4️⃣ 大量 LIKE '%xxx%' / 正则 举具体的例子
好,这一段我给你直接配"反例级"的具体例子 ,而且都用 ClickHouse / Flink SQL 常见写法 来说明 为什么会让向量化"失效或大打折扣"。你可以直接拿去做技术分享或文档里的「⚠️反模式」。
七、什么时候向量化会"失效"(具体例子版)
1️⃣ 复杂 UDF / lambda ------ 跳出向量化执行路径
❌ 例子 1:ClickHouse JavaScript / Python UDF
sql
SELECT
sku_id,
jsFunc('''
function f(x) {
if (x > 100 && x % 7 == 0) {
return x * 1.3;
} else if (x < 50) {
return x * 0.8;
} else {
return x + Math.random();
}
}
''', price) AS score
FROM sku_table;
为什么失效:
- JS UDF 是 逐行调用
- 无法 SIMD
- 无法编译期优化
- 每一行跨语言边界
👉 本质:退化成"for 循环"
❌ 例子 2:Flink SQL 自定义 ScalarFunction
java
public Double eval(Double price, String title) {
if (title.contains("运动")) {
return price * 1.2;
} else if (title.contains("户外")) {
return price * 1.1;
} else {
return price * 0.9;
}
}
sql
SELECT sku_id, score_udf(price, title)
FROM sku_table;
问题:
- 每条数据调用一次 eval
- 字符串操作
- JVM 分支预测失效
✅ 向量化改法
sql
SELECT
sku_id,
price * (1
+ 0.2 * has_sport
+ 0.1 * has_outdoor
) AS score
FROM sku_table;
2️⃣ 每行逻辑分支非常复杂 ------ CPU 分支预测被打爆
❌ 例子:超长 CASE WHEN
sql
SELECT
sku_id,
CASE
WHEN cate = 'A' AND price > 100 AND brand IN (...) THEN 1
WHEN cate = 'B' AND price BETWEEN 50 AND 80 AND sale > 1000 THEN 2
WHEN cate = 'C' AND title LIKE '%运动%' THEN 3
WHEN cate = 'D' AND refund_rate < 0.1 THEN 4
...
ELSE 0
END AS tag
FROM sku_table;
为什么慢:
- 每一行走不同分支
- 分支不可预测
- SIMD 无法统一路径
👉 向量化需要"同一批数据走同一算子"
✅ 向量化改法(拆维度)
sql
SELECT
sku_id,
cate_score
+ price_score
+ brand_score
+ sale_score
+ keyword_score AS total_score
FROM sku_table;
3️⃣ 极端小数据量 ------ 启动成本 > 计算成本
❌ 例子:几十行数据用 CK
sql
SELECT
dotProduct(features, weights)
FROM sku_table
LIMIT 20;
问题:
- 向量批处理有固定成本
- 几十行 SIMD 填不满
- cache / pipeline 都没"热起来"
👉 单条 for-loop 反而更快
⚠️ 典型场景
- 管理后台查 1 个 SKU
- 实时接口查 10 条
- Debug SQL
✅ 建议
| 场景 | 推荐 |
|---|---|
| < 1k 行 | 行模式 / OLTP |
| > 1w 行 | 向量化 |
| > 100w | 向量化 + 并行 |
4️⃣ 大量 LIKE '%xxx%' / 正则 ------ 字符串逐字符扫描
❌ 例子 1:LIKE 前缀通配
sql
SELECT *
FROM sku_table
WHERE title LIKE '%运动%'
OR title LIKE '%户外%'
OR title LIKE '%健身%';
为什么慢:
- 无法利用索引
- 每行字符串逐字符扫描
- SIMD 难以对齐变长字符串
❌ 例子 2:正则灾难
sql
SELECT *
FROM sku_table
WHERE match(title, '(运动|户外|健身).*(鞋|服|器材)');
问题:
- 正则引擎状态机
- 回溯成本高
- 每行一个小解释器
✅ 向量化替代方案
方案 A:关键词 → 数值特征
sql
has_sport UInt8,
has_outdoor UInt8,
has_fitness UInt8
sql
WHERE has_sport + has_outdoor + has_fitness >= 1
方案 B:Bitmap / Set
sql
keyword_bitmap Bitmap
sql
bitmapHasAny(keyword_bitmap, rule_bitmap)
🔚 一句话总结(给你写 PPT 用)
向量化不是"SQL 写得像数学公式就一定快",
一旦引入复杂 UDF、行级分支、字符串模糊匹配,本质就退化回逐行执行。