`

使用KeyOnly特性进行500K对象每秒高效数据处理

阅读更多

在一些实时应用中,如实时产品销售,视频直播弹幕消息等并不希望用户输入太长内容,并且不希望同一用户同一时间发表相同的内容进行刷屏,一般只有一条很短的消息,对于一个十几个字节的Value数据,如果每条使用Key-Value插入,Key-Value读取有点浪费。在iBoxDB中有一种新特性KeyOnly,可以直接把Value压入到Key中,只需要一个Key就可以取得所需要的全部,下面介绍如何在iBoxDB数据库中使用这种KeyOnly的特性。


在iBoxDB中使用KeyValue特性只需要在表名前面加一个'/'符号,引擎就会自动按KeyOnly处理,其它相关操作基本与普通表一致,只有一点小区别就是不会保存非Key的内容,因为没有Value值,所以Update()函数在KeyOnly时总是返回False。可以使用先Delete再Insert模拟更新,也就是KeyValue操作类似字典,KeyOnly操作类似集合。


因为数据库引擎直接支持ORM,使用KeyOnly也可以把Key作为一个对象,下面定义这个Key

public static class ShortMSG { 
  public long productId; 
  public java.util.Date time; 
  public long userId; 
  public String msg; 
}

productId是产品id, time是发表时间, userId是用户id, msg是短消息。这是一个纯Java类。

 

然后在数据库里定义一个与这个类关联的表,表名使用'/'字符开头,如果定义为KeyOnly表,没定义为Key的字段不会被保存。 

db.getConfig()
  .ensureTable(ShortMSG.class, "/shortmsg", "productId", "time", "userId", "msg(30)"); 

 "msg(30)"代表字符串的最大长度是30个字符。一般在应用程序中检测长度,减少数据库的处理。

if ( mymsg.length() <= 30 ){ shortmsg.msg = mymsg; }else{ ... } 

 
其它操作与操作普通数据表一样,在这个测试例子中,使用了100个产品,100个时间点,100个用户发送消息,也就是1,000,000(一百万) 条消息。
数据插入代码

try (Box box = auto.cube()) {
    for (long userid = 1; userid <= count; userid++) {
        ShortMSG smsg = new ShortMSG();
        smsg.productId = fproId;
        smsg.time = new Date(fakeTime + fft);
        smsg.userId = userid;
        smsg.msg = smsg.productId + "-" + (fakeTime + fft) + "-" + smsg.userId;
        box.d("/shortmsg").insert(smsg);
    }
    if (box.commit().equals(CommitResult.OK)) {
        total.addAndGet(count);
    }
}

 数据读取代码:

try (Box box = auto.cube()) {
    for (ShortMSG smsg : box.select(ShortMSG.class, "from /shortmsg where productId==?", fproId)) {
        if (smsg.productId != fproId) {
            System.out.println("Unreachable");
        }
        String cs = smsg.productId + "-" + (smsg.time.getTime()) + "-" + smsg.userId;
        if (!smsg.msg.equals(cs)) {
            System.out.println("Unreachable");
        }
        total.incrementAndGet();
    }
}

 测试结果:

Insert TotalObjects: 1,000,000 FileSize: 158MB
Elapsed 10.314s, AVG 96,955 o/sec

Select TotalObjects: 2,000,000
Elapsed 2.493s, AVG 802,246 o/sec

结果显示使用KeyOnly特性,处理1,000,000(一百万)条短消息只需要大约160MB的硬盘空间,进行2,000,000(二百万)次对象读取只需要2.5 秒,平均每秒读取越过500K个数据对象。


更多资料:
完整代码地址 https://github.com/iboxdb/forjava/tree/master/demos
iBoxDB数据库地址 http://www.iboxdb.com/


如果你在测试中发现超过了1000K对象每秒,这很正常,虚拟机会在运行中优化代码。测试结果在Java8,1G内存下取得,支持Java7,在 Java6下测试只需要把try( box ){  } 修改为 try{ } finally { box.close(); }

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics