招聘网站Hive数据分析
拉勾网每天新增职位大概30万条,招聘Boss直聘的网站活跃HR超过200万。这些数字背后,数据是分析海量的非结构化文本——职位描述、公司介绍、招聘薪资范围、网站技能标签。数据如果用传统MySQL去跑"北京地区Python岗位平均薪资按融资阶段分布"这种查询,分析JOIN三张表就能让DBA想删库跑路。招聘 我们团队去年把招聘数据仓库从PostgreSQL迁到了Hive。网站原因很直接:单月1.2亿条职位记录,数据PostgreSQL的分析索引膨胀到磁盘快撑不住,而Hive on 招聘Tez跑同样的聚合查询,响应时间从47分钟降到6分钟。网站代价是数据没法做行级更新,但招聘数据天然是append-only的,职位下架就标记个状态字段,没人会去改历史快照。 第一版schema设计得很"规范":职位表、公司表、技能标签表三张表拆开,想着符合第三范式。结果每次分析"技能词频与薪资关系"都要关联技能标签表,而那个表因为一个职位挂多个技能标签,数据量膨胀到职位表的4倍。后来改成宽表模式,把技能标签用array 分区策略也调整过。按dt分区是基操,但招聘数据有个特点——周一到周三职位发布量占全周68%,周末只有7%。如果按天均匀分配reduce任务,周一的数据倾斜能让某个reducer跑2小时。后来加了bucket分桶,按company_id哈希到64个桶,配合hive.optimize.skewjoin参数,才算把长尾问题按住。 薪资分布分析是最常被业务方要的。用percentile_approx(salary, array(0.25,0.5,0.75))算分位数,比用row_number()窗口函数快得多。但要注意薪资字段的清洗——"15k-25k·13薪"这种格式,得先用regexp_extract把数字抠出来,再乘13。有次忘了处理"面议"的职位,结果平均薪资算出来是null,被产品经理追着问了三天。 技能共现分析用到了collect_set和自连接。比如想知道"会Spark的人通常还会什么",先按职位ID聚合出技能集合,再explode后自关联。这个查询在Tez上跑了20分钟,出来结果有点反直觉:Spark和Flink的共现率只有12%,但Spark和Hive的共现率高达67%。说明大部分招聘方还是把Spark当SQL加速引擎在用,不是当流处理框架。 公司融资阶段与薪资的关系分析更有意思。用CASE WHEN把融资阶段分成天使轮到D轮以上,再按城市分组算中位数薪资。结果北京D轮以上公司的薪资中位数反而比B轮低8%——大厂职级体系压薪资,创业公司为了抢人反而给得激进。这个结论跟直觉相反,但数据摆在那里。 Hive on Tez的默认并行度经常不够。我们把hive.exec.reducers.bytes.per.reducer从256MB调到128MB,reduce任务数翻倍,整体跑批时间少了35%。代价是YARN队列经常爆满,得跟其他团队抢资源。后来上了Hive on Spark,内存给足的情况下比Tez快20%左右,但GC问题更明显,需要调spark.executor.memoryOverhead。 小文件问题在招聘数据里特别严重。每天30万条职位,如果按dt和city分区,每个分区可能只有几MB。我们跑了定时合并任务,用INSERT OVERWRITE把过去7天的小分区合并成周分区,文件数从12000降到800左右。NameNode的内存压力瞬间下来了。 说到底,Hive在招聘数据分析场景里不是最快的,但它是容错性最好的。某个凌晨ETL任务挂了,第二天早上重新跑一遍就行,不会像流处理那样丢数据。对于T+1的离线分析需求,这个特性比低延迟重要得多。建表时踩过的坑
几个实际跑过的分析场景
性能调优的土办法
-
上一篇
-
下一篇
- 随机阅读
- 搜索
-
- 友情链接
-