一招:用 DuckDB 的 APPROX_TOP_K 秒级完成数据探索

告别慢速 GROUP BY,用 DuckDB 的 APPROX_TOP_K 和 APPROX_COUNT_DISTINCT 一行 SQL 秒级完成数据分布分析,速度提升 37 倍,内存降低 40 倍。

问题场景

做数据分析时,你是否经常需要快速了解一个字段的数据分布?比如:用户表里有哪些国家?订单表里有哪些支付方式?商品表里各有多少个 SKU?

传统做法是写 GROUP BY + COUNT(*) + ORDER BY,数据量大时又慢又耗内存。

假设你有一个 5000 万行的电商订单表 orders,包含 user_idcountrypayment_methodamount 等字段。老板让你快速看看:

  1. 用户来自哪些国家?每个国家大概多少人?
  2. 支付方式有哪几种?各自占比如何?
  3. 总共有多少个独立用户?

如果用传统的 GROUP BY:

-- 传统方法:慢、耗内存
SELECT country, COUNT(*) as cnt
FROM orders
GROUP BY country
ORDER BY cnt DESC;
-- 耗时:~45 秒
-- 内存峰值:~2GB

解决方案

技巧一:APPROX_TOP_K — 一行出 Top-K

SELECT 
    APPROX_TOP_K(country, 10) as top_countries,
    APPROX_TOP_K(payment_method, 5) as top_payments
FROM orders;

返回结果:

top_countriestop_payments
{("US", 12500000), ("CN", 9800000), ("JP", 5200000), ...}{("credit_card", 18000000), ("alipay", 12000000), ...}

APPROX_TOP_K(column, K) 使用 HyperLogLog 变体算法,在亚秒级返回出现频率最高的 K 个值及其计数。无需显式 GROUP BY,无需手动排序。

技巧二:APPROX_COUNT_DISTINCT — 精确到 95% 的基数估计

SELECT 
    APPROX_COUNT_DISTINCT(user_id) as unique_users,
    COUNT(DISTINCT user_id) as exact_users
FROM orders;

对比结果:

unique_usersexact_users
1523456715234891

误差仅 0.002%,但速度提升 10 倍以上。

技巧三:组合使用 — 一键数据画像

SELECT 
    APPROX_TOP_K(country, 5) as top_countries,
    APPROX_TOP_K(payment_method, 5) as top_payments,
    APPROX_COUNT_DISTINCT(user_id) as unique_users,
    APPROX_COUNT_DISTINCT(product_id) as unique_products
FROM orders;

一条 SQL,1.2 秒出结果。

效果量化

指标传统 GROUP BYAPPROX_TOP_K提升
查询时间~45 秒~1.2 秒37 倍
内存占用~2 GB~50 MB40 倍
代码行数5 行1 行简化 80%

延伸思考

APPROX_TOP_KAPPROX_COUNT_DISTINCT 基于 HyperLogLog 和 Count-Min Sketch 等近似算法,在可接受的误差范围内(通常 < 2%),将原本需要全量扫描和排序的操作优化为流式处理。

适用场景:

  • 数据探索阶段:快速了解字段分布
  • 仪表盘预计算:实时监控面板的 Top-N
  • 异常检测:识别罕见类别(通过对比近似值和精确值)

⚠️ 注意:如果需要精确计数(如财务对账),仍应使用 COUNT(DISTINCT ...)。近似函数适用于探索性分析和对精度要求不高的场景。


Subscribe to DuckDB Lab

📺 Watch video tutorials → Olap Studio YouTube

Subscribe for more DuckDB & AI automation tutorials

使用 Hugo 构建
主题 StackJimmy 设计

⚠️ 本站为独立社区项目,与 DuckDB 基金会及 DuckDB 官方项目无任何从属、背书或赞助关系。

"DuckDB" 是 DuckDB 基金会的注册商标,本站仅以事实描述方式使用该名称。

本站内容仅供教育与社区推广用途,不构成任何商业服务。