很多数据开发者使用bitmap技术对用户数据进行编码和压缩,然后利用bitmap的与/或/非的极速处理速度,实现类似用户画像标签的人群筛选、运营分析的7日活跃等分析。
本文给出了一个使用MaxCompute MapReduce开发一个对不同日期活跃用户ID进行bitmap编码和计算的样例。供感兴趣的用户进一步了解、分析,并应用在自己的场景下。


import com.aliyun.odps.OdpsException;
import com.aliyun.odps.data.Record;
import com.aliyun.odps.data.TableInfo;
import com.aliyun.odps.mapred.JobClient;
import com.aliyun.odps.mapred.MapperBase;
import com.aliyun.odps.mapred.ReducerBase;
import com.aliyun.odps.mapred.conf.JobConf;
import com.aliyun.odps.mapred.utils.InputUtils;
import com.aliyun.odps.mapred.utils.OutputUtils;
import com.aliyun.odps.mapred.utils.SchemaUtils;
import org.roaringbitmap.RoaringBitmap;
import org.roaringbitmap.buffer.ImmutableRoaringBitmap; import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.util.Base64;
import java.util.Iterator; public class bitmapDemo2
{ public static class BitMapper extends MapperBase { Record key;
Record value;
@Override
public void setup(TaskContext context) throws IOException {
key = context.createMapOutputKeyRecord();
value = context.createMapOutputValueRecord();
} @Override
public void map(long recordNum, Record record, TaskContext context)
throws IOException
{
RoaringBitmap mrb=new RoaringBitmap();
long AID=0;
{
{
{
{
AID=record.getBigint("id");
mrb.add((int) AID);
//获取key
key.set(new Object[] {record.getString("active_date")}); }
}
}
}
ByteBuffer outbb = ByteBuffer.allocate(mrb.serializedSizeInBytes());
mrb.serialize(new DataOutputStream(new OutputStream(){
ByteBuffer mBB;
OutputStream init(ByteBuffer mbb) {mBB=mbb; return this;}
public void close() {}
public void flush() {}
public void write(int b) {
mBB.put((byte) b);}
public void write(byte[] b) {mBB.put(b);}
public void write(byte[] b, int off, int l) {mBB.put(b,off,l);}
}.init(outbb)));
String serializedstring = Base64.getEncoder().encodeToString(outbb.array());
value.set(new Object[] {serializedstring});
context.write(key, value);
}
} public static class BitReducer extends ReducerBase {
private Record result = null; public void setup(TaskContext context) throws IOException {
result = context.createOutputRecord();
} public void reduce(Record key, Iterator<Record> values, TaskContext context) throws IOException {
long fcount = 0;
RoaringBitmap rbm=new RoaringBitmap();
while (values.hasNext())
{
Record val = values.next();
ByteBuffer newbb = ByteBuffer.wrap(Base64.getDecoder().decode((String)val.get(0)));
ImmutableRoaringBitmap irb = new ImmutableRoaringBitmap(newbb);
RoaringBitmap p= new RoaringBitmap(irb);
rbm.or(p);
}
ByteBuffer outbb = ByteBuffer.allocate(rbm.serializedSizeInBytes());
rbm.serialize(new DataOutputStream(new OutputStream(){
ByteBuffer mBB;
OutputStream init(ByteBuffer mbb) {mBB=mbb; return this;}
public void close() {}
public void flush() {}
public void write(int b) {
mBB.put((byte) b);}
public void write(byte[] b) {mBB.put(b);}
public void write(byte[] b, int off, int l) {mBB.put(b,off,l);}
}.init(outbb)));
String serializedstring = Base64.getEncoder().encodeToString(outbb.array());
result.set(0, key.get(0));
result.set(1, serializedstring);
context.write(result);
}
}
public static void main( String[] args ) throws OdpsException
{ System.out.println("begin.........");
JobConf job = new JobConf(); job.setMapperClass(BitMapper.class);
job.setReducerClass(BitReducer.class); job.setMapOutputKeySchema(SchemaUtils.fromString("active_date:string"));
job.setMapOutputValueSchema(SchemaUtils.fromString("id:string")); InputUtils.addTable(TableInfo.builder().tableName("bitmap_source").cols(new String[] {"id","active_date"}).build(), job);
// +------------+-------------+
// | id | active_date |
// +------------+-------------+
// | 1 | 20190729 |
// | 2 | 20190729 |
// | 3 | 20190730 |
// | 4 | 20190801 |
// | 5 | 20190801 |
// +------------+-------------+
OutputUtils.addTable(TableInfo.builder().tableName("bitmap_target").build(), job);
// +-------------+------------+
// | active_date | bit_map |
// +-------------+------------+
// 20190729,OjAAAAEAAAAAAAEAEAAAAAEAAgA=3D
// 20190730,OjAAAAEAAAAAAAAAEAAAAAMA
// 20190801,OjAAAAEAAAAAAAEAEAAAAAQABQA=3D JobClient.runJob(job);
}
}

对Java应用打包后,上传到MaxCompute项目中,即可在MaxCompute中调用该MR作业,对输入表的数据按日期作为key进行用户id的编码,同时按照相同日期对bitmap后的用户id取OR操作(根据需要可以取AND,例如存留场景),并将处理后的数据写入目标结构表当中供后续处理使用。

本文作者:圣远

原文链接

本文为云栖社区原创内容,未经允许不得转载。

在MaxCompute中利用bitmap进行数据处理的更多相关文章

  1. Android中利用C++处理Bitmap对象

    相信有些Android&图像算法开发者和我一样,遇到过这样的状况:要对Bitmap对象做一些密集计算(例如逐像素的滤波),但是在java层写循环代码来逐像素操作明显是不现实的,因为Java代码 ...

  2. 如何简单地利用Bitmap为中介储存图片到数据库中

        这是我的第一篇博文,请大家多多指教!     大概一个月之前,在跟朋友合作开发一个APP的过程中,我们发现到一个问题:图片的存储.因为数据库没有图片这种数据类型,当用户上传的图片需要存储的时候 ...

  3. C#中的bitmap类和图像像素值获取方法

    一.Bitmap类 Bitmap对象封装了GDI+中的一个位图,此位图由图形图像及其属性的像素数据组成.因此Bitmap是用于处理由像素数据定义的图像的对象.该类的主要方法和属性如下: 1. GetP ...

  4. Android下利用Bitmap切割图片

    在自己自定义的一个组件中由于需要用图片显示数字编号,而当前图片就只有一张,上面有0-9是个数字,于是不得不考虑将其中一个个的数字切割下来,需要显示什么数字,只需要组合一下就好了. 下面是程序的关键代码 ...

  5. Hadoop 中利用 mapreduce 读写 mysql 数据

    Hadoop 中利用 mapreduce 读写 mysql 数据   有时候我们在项目中会遇到输入结果集很大,但是输出结果很小,比如一些 pv.uv 数据,然后为了实时查询的需求,或者一些 OLAP ...

  6. [原创]MYSQL中利用外键实现级联删除和更新

    MySQL中利用外键实现级联删除.更新 MySQL支持外键的存储引擎只有InnoDB,在创建外键的时候,要求父表必须有对应的索引,子表在创建外键的时候也会自动创建对应的索引.在创建索引的时候,可以指定 ...

  7. [.net 面向对象程序设计进阶] (21) 反射(Reflection)(下)设计模式中利用反射解耦

    [.net 面向对象程序设计进阶] (21) 反射(Reflection)(下)设计模式中利用反射解耦 本节导读:上篇文章简单介绍了.NET面向对象中一个重要的技术反射的基本应用,它可以让我们动态的调 ...

  8. PHP中利用GD实现的柱状图

    PHP中利用GD实现的柱状图,自己写的一个画柱状图的类,上代码. <?php Class Chart{ private $image; // 定义图像 private $title; // 定义 ...

  9. springMVC中利用model在JSTL进行回填值

    1.ringMVC中利用model回填值 后台中,利用model返回值,如 model.addAttribute("MS_info" , MS_info); 前台回填值: text ...

随机推荐

  1. 出错提示:“Could not flush the DNS Resolver Cache: 执行期间,函数出了问题”的解决方法

    在DNS解析中,出错提示:"Could not flush the DNS Resolver Cache: 执行期间,函数出了问题"的解决方法  . 由于公司网站空间更换了服务商. ...

  2. elasticDump的安装使用

    官方地址:官方地址:https://github.com/taskrabbit/elasticsearch-dump 安装方式如下:安装NodeJS下载源码:wget http://nodejs.or ...

  3. Linux CentOS CapsLock 大小写反转问题 解决

    虚拟机centos7,输入大小写字母反了,开启capslock的时候变成小写字母了,关闭则变成大写了... 只需要执行 setleds +caps 或 setleds -caps 即可,如图:

  4. 怎么解决VirtualBox无法安装增强工具

    点击「设备」-「安装增强功能」,然后就弹出下面这个东西,百度和 bing 了很久,终于解决啦~ Unable to insert the virtual optical disk D:\Program ...

  5. redis String 命令

    今天在虚拟机的Ubuntu上装了一个redis,学习redis的一些基本东西,在数据类型的时候,看到redis的,String,hash,set list zset,对String的setbit命令一 ...

  6. Android 开发 AudioRecord音频录制

    前言 Android SDK 提供了两套音频采集的API,分别是:MediaRecorder 和 AudioRecord,前者是一个更加上层一点的API,它可以直接把手机麦克风录入的音频数据进行编码压 ...

  7. Java 普通代码块,构造代码块,静态代码块

    具体百度... 这里只记下,构造构造代码块在构造函数之前执行,每创建一个对象则执行一次. 静态代码块属于类,而不是对象,只执行一次.

  8. linux查看磁盘大小,使用量等等信息

    第一:统一磁盘整体情况 1.查看当前目录命令 df -h 结果: 统一每个目录下磁盘的整体情况 2.查看指定目录在命令后直接放目录名,比如查看“usr”目录使用情况: df -h /usr/结果: 统 ...

  9. [转载] OpenCV2.4.3 CheatSheet学习(二)

    二.矩阵操作(拷贝.洗牌.局部访问): src.copyTo(dst) 把src矩阵中的数据拷贝到dst. src.convertTo(dst, type,scale, shift) 缩放并转换到另外 ...

  10. xml文件节点读取时,selectNodes总是在根节点下查找的问题

    参考:https://yq.aliyun.com/articles/39543 SAXReader reader = new SAXReader();Document document = reade ...