在一些实时应用中,如实时产品销售,视频直播弹幕消息等并不希望用户输入太长内容,并且不希望同一用户同一时间发表相同的内容进行刷屏,一般只有一条很短的消息,对于一个十几个字节的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(); }