当前位置: 首页 > news >正文

【Hive】三、Hive 抽样:讲解 Hive 三大抽样方式:分桶抽样、块抽样、随机抽样的原理、语法、性能对比与实战案例

文章目录

  • 二、Hive 抽样的三大类型
  • 三、分桶抽样(TABLESAMPLE+BUCKET 最推荐)
    • 1. 分桶表的核心设计
    • 2. 分桶抽样执行流程
  • 四、块抽样(TABLESAMPLE)
    • 1、按数据大小百分比抽样
    • 2、按固定大小抽样
    • 3、按行数抽样
    • 4、❌TABLESAMPLE + WHERE
      • 4.1、一起使用导致的问题
      • 4.2、替代方案
        • 1)WHERE + RAND
        • 2)子查询包装
        • 3)CTE表达式
        • 4)临时表存储
        • 5)精确行数抽样
  • 五、随机抽样(RAND)
    • 5.1、概率过滤
    • 5.2、可复现随机样本
    • 5.3、局部随机
    • 5.4、全局随机
    • ×分层抽样(按分组比例)
    • 五、实战案例:用户行为分析抽样
      • 场景:分析国庆期间高活跃用户

我的网站原文:https://eleanora-lyh.github.io/MyLearningNotes/
csdn处的文章会尽快同步更新,欢迎大家来访问!

在 Hive 场景中:

  • 数据量:TB / PB 级
  • 查询方式:MapReduce / Spark(高延迟)
  • 全表扫描成本极高

👉 所以抽样的本质是:

用小数据近似大数据特征(加速分析/调试)


二、Hive 抽样的三大类型

Hive 一共有 3 种主流抽样方式:

类型关键语法随机性性能是否需要分桶
✅ 分桶抽样(Bucket Sampling)TABLESAMPLE(BUCKET …)✅ 好✅ 高✅ 必须
✅ 块抽样(Block Sampling)TABLESAMPLE(…)❌ 差✅ 非常高
✅ 随机抽样(Random Sampling)rand() + limit✅ 真随机❌ 较差

三、分桶抽样(TABLESAMPLE+BUCKET 最推荐)

最推荐的高性能抽样方式,利用Hive分桶机制直接定位数据块,速度最快。

1. 分桶表的核心设计

通过建表的分桶设计,在物理层面上按照bucket_id = hash(user_id) % 32数据均匀分布到32个桶中,之前学到的分桶可以优化两个分桶表的JOIN操作,使得JOIN时user_id相同的一定落在同一个桶中(一个节点内),避免了不同node节点之间的shuffle(无需将同一个键值的记录汇总到一起,分桶建表时就已经放入同一个桶中了)。

传统HDFS存储: data_2023-10-01.txt(包含所有user_id的记录)data_2023-10-02.txt 分桶表存储结构:/user/hive/warehouse/user_bucketed/dt=2023-10-01/├──000000_0(bucket-00000)-user_id哈希值%32=0的记录 ├──000001_0(bucket-00001)-user_id哈希值%32=1的记录 ├──...└──000031_0(bucket-00031)-user_id哈希值%32=31的记录 分桶文件命名规则 分桶文件名格式: bucket文件:00000N_0-6位: 桶编号(5位数字,从00000开始)-下划线: 分隔符-最后数字: 桶内文件编号(分桶文件可再分小文件) 示例:000025_0-桶编号:25-文件编号:0(第一个文件)

我们可以理解为分桶优化了表的存储方式,使得在查找时无需进行复杂的数据交换。

分桶抽样之所以成立,是因为 hash(user_id)近似均匀分布→ 随机选一个 bucket ≈ 全局数据的一个“随机子集”。

2. 分桶抽样执行流程

相信现在你已经明白为什么会有分桶抽样了,通过分桶建表,我们将数据随机分布在桶中,所以通过抽取桶就可以等价于随机抽样。可以理解为空间换时间,事先将数据准备好了,这样随机抽样时无需遍历所有的行来达到随机的效果。

-- 1. 创建分桶表CREATETABLEuser_bucketed(user_idBIGINT,user_name STRING,)CLUSTEREDBY(user_id)INTO32BUCKETS STOREDASORC;-- 2. 查询示例 基于分桶列的抽样(需已创建分桶表)SELECT*FROMuser_bucketed TABLESAMPLE(BUCKET3OUTOF8ONuser_id);-- 注意:Hive中的桶编号是0-based(从0开始)但在TABLESAMPLE语法中,x是1-based(从1开始)-- 执行过程分解:1.计算抽样桶号:桶数=32,抽样组数=32/8=4(最后会取出4个桶,相当于抽取了4/32=1/8的数据)2.目标桶: k=0:2+0×8=2k=1:2+1×8=10k=2:2+2×8=18k=3:2+3×8=26k=4:2+4×8=3432,停止 得到3,3+8=11,3+16=19,3+24=273.直接读取4个对应的HDFS文件:000002_0,000010_0,000018_0,000026_04.无需全表扫描,直接定位物理文件,返回结果

参数说明BUCKET x OUT OF y ON col

  • y:总桶数(必须是分桶数的约数)
  • x:抽取的桶编号(从1开始)
  • 抽样比例 =1/y

如果表不是分桶表,但是仍使用分桶抽样,如下

-- 随机分桶抽样(无需分桶列)SELECT*FROMuser_bucketed TABLESAMPLE(BUCKET3OUTOF8ONRAND())s;

则具体执行过程:

  • 1️⃣ 启动MapReduce任务,全表扫描每一行(因为没有预分桶)

  • 2️⃣ 对每一行执行

    • 调用RAND()生成随机数
    • 计算RAND()值的哈希:hash(rand())
    • 哈希值对8取模,得到桶号(0-7):bucket_id = hash(rand()) % 32(虚拟bucket)
  • 3️⃣ 过滤出桶号=2的行

  • 4️⃣ 输出数据

👉 本质 = 全表 scan + 行级 hash + 过滤


四、块抽样(TABLESAMPLE)

本质是直接在 HDFS 数据块(block)(默认128MB/256MB)层面做抽样,而不是逐行随机抽

步骤:

  • 1️⃣ 获取文件列表(Partition / Directory)
  • 2️⃣ 生成 InputSplit(HDFS block)
  • 3️⃣ 按比例选部分 InputSplit ✅(关键,1-3步多是发生在scan之前)
  • 4️⃣ Map任务只读取这些 block(scan)
  • 5️⃣ 输出数据

举例:已知表 = 1TB,block = 128MB。执行快抽取10%的步骤如下

总共 1T/128M ≈ 8000 个 block,执行TABLESAMPLE(10 PERCENT)时,Hive从8000个block中随机选800个,只启动对应的 map task(只启动对应的 map task)

👉 因此:

speed非常快(减少IO)
不严格随机(受数据分布影响,比如按日期分区写入, block 抽样可能只抽到某几天的数据,抽的是文件块,而不是打散后的数据)

1、按数据大小百分比抽样

抽取原hive表中10%的数据,并保存到新表中

SELECT*FROMlogs TABLESAMPLE(0.1PERCENT)

2、按固定大小抽样

抽样SELECT*FROMlogs TABLESAMPLE(100M)

3、按行数抽样

按行数抽样(可能不准确,因Hive不严格维格维护行数)

SELECT*FROMlogs TABLESAMPLE(1000ROWS);

✅ 适合场景

✔ 快速预览数据
✔ 调试 pipeline
❌ 不适合统计分析(不随机)

4、❌TABLESAMPLE + WHERE

4.1、一起使用导致的问题

无法和where一起使用:根据块抽样的执行步骤可知,TABLESAMPLE发生在scan读取之前 ,WHERE发生在数据读取后,所以二者同时出现就会导致结果比例不确定、抽样失去意义、Hive 难以保证正确性的问题,具体如下:

1)结果比例不确定

举个例子:10% 的 gender='F'意思是先找到gender='F'的所有记录,再从中抽取10%

但是如果使用TABLESAMPLEWHERE=> 先选取10% block → 再筛选 gender=‘F’。👉 最终可能 <10%

2)抽样失去意义

gender='F'本来只有 5%。 先抽block,可能抽不到任何 female 记录

3)Hive 难以保证正确性的问题

Hive设计原则:抽样应该严格作用在表级别,而不是过滤后数据

4.2、替代方案

1)WHERE + RAND

先过滤,再抽样的逻辑正确

SELECT*FROMtableWHEREgender='F'ANDRAND()<=0.1;
2)子查询包装
-- 先抽样,后过滤SELECT*FROM(SELECT*FROMuser_behavior TABLESAMPLE(1PERCENT)-- 全表1%的块)sampled_dataWHEREevent_type='click';-- 在抽样结果中过滤-- 先过滤,后抽样SELECT*FROM(SELECT*FROMuser_behaviorWHEREdt='2023-10-01'-- 先按条件筛选)filtered_data TABLESAMPLE(10PERCENT);-- 在筛选结果上抽样= 0.1;
3)CTE表达式
WITHsampled_ordersAS(SELECT*FROMorders TABLESAMPLE(100M))SELECT*FROMsampled_ordersWHEREamount>1000ANDstatus='COMPLETED';
4)临时表存储
-- 1. 创建抽样临时表CREATETEMPORARYTABLEtemp_sampleASSELECT*FROMlarge_table TABLESAMPLE(0.5PERCENT);-- 2. 在临时表上执行复杂查询SELECTuser_id,COUNT(*)ascntFROMtemp_sampleWHEREevent_time>='2023-10-01'GROUPBYuser_idHAVINGcnt>5;
5)精确行数抽样
SELECT*FROM(SELECT*FROMtableWHEREgender='F'DISTRIBUTEBYrand()SORTBYrand())tLIMIT1000;

五、随机抽样(RAND)

最灵活的抽样方式,但需要全表扫描,性能较差。

limit关键字限制抽样返回的数据,其中rand函数前的distribute和sort关键字可以保证数据在mapper和reducer阶段是随机分布的。

5.1、概率过滤

步骤:

  • Map scan
  • 过滤:每一行执行rand(123) -> 0~1满足条件<= 0.1的保留。(没有固定种子,每次就可以得到不同的随机序列)
  • 输出

👉 本质:每行独立 Bernoulli 抽样(概率采样)

所以没有Reduce阶段、全局排序、网络shuffle

-- 随机抽取10%的数据SELECT*FROMordersWHERERAND()<=0.1;

适合场景

  • ✔ 大数据快速抽样
  • ✔ SQL调试
  • ✔ 统计分析近似

结果行数 ≠ 精确10% (因为WHERE RAND() <= 0.1的概率抽样是波动的)

5.2、可复现随机样本

步骤:

  • Map scan
  • 过滤:每一行执行rand(123) -> 0~1满足条件<= 0.05的保留。(固定种子为123,每次就可以得到相同的随机序列)
  • shuffle:DISTRIBUTE BY RAND(123)把数据随机打散到 reducer
  • 局部排序:SORT BY RAND(123)每个reducer内部排序
-- 可重现的随机抽样(设置随机种子)SELECT*FROMordersWHERERAND(123)<=0.05-- 固定种子,结果可重现DISTRIBUTEBYRAND(123)SORTBYRAND(123)LIMIT1000;

适合场景

  • ✔ 实验可复现(A/B Test)
  • ✔ 调试稳定样本
  • ✔ 模型训练数据抽样

5.3、局部随机

步骤:

  • Map scan
  • shuffle:DISTRIBUTE BY RAND()把数据随机打散到 reducer
  • 局部排序:SORT BY RAND()每个reducer内部排序
SELECT*FROMordersWHEREcol='xxx'DISTRIBUTEBYRAND()SORTBYRAND()LIMIT1000;
  • ORDER BY RAND()
  • WHERE RAND()更随机

但是它不是全局随机!(因为多个 reducer 各自排序)👉 偏随机(但不是严格均匀)

5.4、全局随机

步骤:

  • Map scan
  • shuffle:所有数据 shuffle 到一个reducer节点
  • 全局排序:ORDER BY RAND()1个reducer内部全局排序
SELECT*FROMordersORDERBYrand()LIMIT1000;

完全随机,但是单reducer和全shuffle会导致整个过程很慢

适合场景

✔ 少量数据
✔ 强随机要求

❌ 不适合大表

写法抽样方式是否全表扫描是否Shuffle随机性性能
WHERE RAND() <= p✅ 概率过滤✅ 是❌ 否✅ 好✅ 高
RAND(seed)+ distribute/sort✅ 可复现随机✅ 是✅ 有✅ 很好⚠️ 中
distribute by rand() sort by rand()✅ 局部随机✅ 是✅ 有⚠️ 一般⚠️ 中
order by rand()✅ 全局随机✅ 是✅ 超大✅ 最好❌ 慢

×分层抽样(按分组比例)

-- 每个城市抽取5%的用户SELECT*FROM(SELECT*,ROW_NUMBER()OVER(PARTITIONBYcityORDERBYRAND())asrn,COUNT(*)OVER(PARTITIONBYcity)astotalFROMusers)tWHERErn<=total*0.05;

五、实战案例:用户行为分析抽样

场景:分析国庆期间高活跃用户

-- 错误做法(可能漏掉目标用户)SELECTuser_id,COUNT(*)aslogin_countFROMuser_logs TABLESAMPLE(100M)-- 随机块,可能不包含国庆数据WHERElogin_dateBETWEEN'2023-10-01'AND'2023-10-07'GROUPBYuser_idHAVINGlogin_count>10;-- 正确做法1:先过滤后抽样SELECT*FROM(SELECTuser_id,COUNT(*)aslogin_countFROMuser_logsWHERElogin_dateBETWEEN'2023-10-01'AND'2023-10-07'GROUPBYuser_idHAVINGlogin_count>10)active_users TABLESAMPLE(20PERCENT);-- 在结果集上抽样-- 正确做法2:分桶表高效查询CREATETABLEuser_logs_bucketed(user_idBIGINT,login_date STRING)CLUSTEREDBY(user_id)INTO100BUCKETS PARTITIONEDBY(dt STRING)STOREDASORC;-- 分区剪枝 + 分桶抽样SELECTuser_id,COUNT(*)aslogin_countFROMuser_logs_bucketed TABLESAMPLE(BUCKET1OUTOF20ONuser_id)WHEREdtBETWEEN'2023-10-01'AND'2023-10-07'GROUPBYuser_id;
http://www.jsqmd.com/news/964210/

相关文章:

  • 印尼旅游如何挑选靠谱旅行社?宜事旅游服务解析 - 资讯速览
  • 2026 高考生凭准考证选购苹果手机|完整优惠攻略(线上 + 线下 + 国补 + 618 叠加) - 资讯速览
  • 第2周学习笔记
  • Agent S3:让AI像人类一样操作电脑的智能助手
  • YOLO26自适应注意力魔改:让模型在训练中自动决定选用通道还是空间注意力
  • 在线查询IP归属地攻略:三步锁定精确地理位置,新手也能用(2026版)
  • 百草枯农药残留检测卡快速检测果蔬中的百草枯农药残留
  • 2026流程图工具选型:5款产品深度对比,帮你找到最适合团队的方案
  • 新手入门:通过快马生成的代码轻松理解timed_out编程概念
  • Xilinx Virtex-5 FPGA DDR2 SDRAM接口调试全流程与避坑指南
  • 5分钟找回十年青春:GetQzonehistory一键备份QQ空间完整记忆
  • 特朗普手机号称美国制造却困难重重,真能实现目标吗?
  • 如何永久免费使用IDM:一键激活脚本完整指南
  • 终极Sketch标注插件:Sketch MeaXure完整指南,让设计交付效率提升300%
  • 深度修复:Flow Launcher文件搜索失效的3步诊断与解决方案
  • 2026甄选:涉密资质服务公司核心能力与适配性分析 - 品牌企业推荐师(官方)
  • 2026.06.06 6666666
  • 实测5种Prompt模板对比100次查询性能
  • 利用快马平台快速生成串口调试助手原型,十分钟搞定嵌入式通信测试工具
  • JS详解:Boolean()与!!双感叹号的区别、用法、底层原理(前端必看)
  • 从DAG到值编码:手把手教你用Python可视化编译原理中的表达式优化过程
  • QQ截图独立版:从零开始打造Windows最强截图工作流
  • 南京微短剧产业迎来“高光时刻”:“百部真人短剧集群”盛大开机 - 资讯速览
  • 零基础学全栈:借助快马AI生成‘面具公社’源码,轻松入门网页开发
  • 工程师招聘:从应试筛选到双向技术对话的实践与思考
  • 2026年免费在线抠图工具推荐:一看就会的网页版详细教程
  • PDF转Excel/PPT/图片及压缩,2026年度免费工具横评:速度、精度、隐私安全全对比 - 时时资讯
  • 2026年想去成都电竞网咖,哪家性价比高能让我玩得值
  • ai辅助开发:如何用快马平台的kimi模型迭代出理想中的跳转页面样式
  • OmenSuperHub终极指南:如何为惠普OMEN游戏本实现专业级性能控制