Oracle NoSQL学习的一点心得

时间:2022-10-27 11:11:37

一、无心之谈

项目需要,需要使用Oracle NoSQL数据库,才开始了Oracle NoSQL摸索之旅。

Oracle NoSQL很年轻,目前才更新到3.2.5版本,其功能尚不完全,官方帮助文档简略,尤其是开发API的文档。使得博主在项目进行中尝尝遇到很多问题,又不能很方便的找到解决方案。所以,这些都促使我每次有点收获的时候总想记下来,一方面可以供自己以后学习,另一方面可以供后来人参考.

目前,使用Oracle NoSQL遇到不明白的地方,最好的求助方法就是去官网论坛上发帖,Oracle NoSQL内部人士会热心详细解答,官方论坛

二、一点点心得

1)multiGet() method

这个方法用于一次返回多条记录,只要这些记录的 shard key一样
Table API(3.2.5版本)中是这样说的:
Oracle NoSQL学习的一点心得

但是,这其实是帮助文档的一个bug。使用multiGet方法时必须指定全部的shard key,部分shard key是不行的。
Shark Key一定是主键的子集,指定主键的时候注意顺序,顺序很重要。请查看帮助文档。

2)索引问题

1.Array index

Oracle NoSQL支持数组索引,听上去是不是很有诱惑力?!对于学地理的我来说,感觉很实用。但是,不用不知道,一用就。。。。
比如我有个一个字段为coordinate,存储的是坐标(coordinate.add(x),coordinate.add(y)),然后对其建立的索引。查询的时候却只能指定一个单一的值,并不能同时给定x,y坐标值然后进行查询。
举个通俗的例子,现有一个字段存储的都是这样的数组:["one","two","three","four"],["one","six","seven","ten"]......
但是查询的时候只能指定一个值,比如指定值为“one”,则字段数组中包含“one”的记录都会返回。并不支持查询特定的一个数组。

2.multi-Index

后来在官网论坛上发帖,无意得知的一个信息。Oracle NoSQL支持对多个字段建立一个索引,比如:
-index index_name -field time -field lat -field lon
它的意思就是对时间、经纬度这三个字段建立一个名为index_name的索引。
这个特性特别有用。尤其是在应用需要使用组合查询的时候,对多个字段建立一个索引,就可以指定多个字段的值进行查询。

使用muli-index进行范围查询问题【这里有官方论坛上的回复,点击这里
如上面所示,现已对time、lat、lon三个字段建立了一个名为index_name索引。那么,我能够利用利索引,同时分别指定time、lat和lon的范围进行查询吗?
答案是否定的。只能对time字段进行范围查询。【下面的实验会证明这一点,同时我们可以得出, 在建立多字段索引的时候,指定字段的顺序是很有关系的

指定时间进行查询:
Oracle NoSQL学习的一点心得

如果指定经纬度的范围,而不指定时间范围,进行查询:
Oracle NoSQL学习的一点心得
会提示错误。

指定经纬度范围和时间范围,但是time字段 最后指定
Oracle NoSQL学习的一点心得

可以看出,是可以进行查询的,但是返回的结果只满足时间范围的要求。

指定经纬度和时间范围,但是time字段 不最后指定
Oracle NoSQL学习的一点心得
同样,会提示错误。


另外,可以指定时间的范围,再指定经度和纬度的值(这里不是范围)进行查询,同时这三个字段的顺序没有关系:
Oracle NoSQL学习的一点心得

或者指定时间范围和lat的值(这里不是范围)进行查询。
但是,不能指定时间的范围和lon的值进行查询:[这点与MongoDB不同]
Oracle NoSQL学习的一点心得
这是为什么呢?前面已经说过,建立多字段索引的时候,指定字段的顺序是有影响的。(-index index_name -field time -field lat -field lon)
MongoDB中是支持这点的:【原文请 查看这里
Oracle NoSQL学习的一点心得

3)数据膨胀问题

原始数据存入Oracle NoSQL之后会膨胀几十倍有时候,特别是建立了索引之后,有时候夸张的膨胀了接近100倍(4.29G原始数据,变成320G)是不是很夸张!!!!
这个原因我还不清楚,还在继续寻找答案。待我有了答案,会在这里进行说明。这里暂时贴出论坛上别人给出的解释:

Oracle NoSQL学习的一点心得

数据膨胀问题,我找到了原因:
我的数据库目录下挂载了五六个卷(在云上称为卷,这里我们暂且等同于磁盘吧),这个地方就是问题所在。一个目录下怎么能挂载多个磁盘呢?!!!!
当你在同一个挂载第二个磁盘时,第一个挂载的磁盘会隐藏,当挂载第三个磁盘时,第二个磁盘就会被隐藏,以此类推。所以,当在同一个磁盘下挂载多个磁盘时,其实仅仅挂载了最后一个磁盘而已。
那么,一个磁盘的容量不够大,不满足要求,如何利用多个磁盘构建一个大点的”磁盘“然后挂载到一个目录下呢?这就要利用软件磁盘阵列了,请参看《鸟哥的Linux私房菜基础学习片(第三版)》第469页。
关于磁盘阵列,有一点需要这个注意就是磁盘阵列的模式。它有多种模式,每个模式有优缺点,根据自己的需求构建相应模式的磁盘阵列(即RAID)。这方面的详细信息请参看《鸟哥的Linux私房菜基础学习片(第三版)》第463页。一下RAID-0和RAID-1的解释截图:
Oracle NoSQL学习的一点心得Oracle NoSQL学习的一点心得

4)有ChildTable的数据写入问题

当表还有子表的时候,写入子表的每条记录都要同时指定对应父表的主键的值。但是在定义子表的时候,不需要指定父表主键那几个字段。
所以,相当于父表的主键存储了两遍。那么,当主键指定较多的时候就要考虑数据存储空间的问题了,因为主键的冗余存储会占用很多空间,这时候可以考虑下使用record来代替子表。当然,如果你的存储空间足够大,那就另当别论。

5) tableIterator方法与multiGet方法对比

 “tableIterator() is less efficient than multiGet() and not transactional”---来自Oracle NoSQL内部人士。

6)范围查询(FieldRange)


以下摘自我在官方论坛上发帖得到的回复(原文点击这里):

Oracle NoSQL DB supports range queries. You could implement regex()-type pattern matching in your client to filter out the rows that you don't want. Regex style and other pattern matching expressions will be supported in the future.

 

Here's an example of using either the Shard Key within a Primary Key index or using a Secondary Key index to index and fetch a range of values using the KV CLI shell:

 

exec "create table example1 (ID integer, NAME STRING, Primary Key (NAME))"

put table -name example1 -json '{"ID":1,"NAME":"ABCDEF"}'

put table -name example1 -json '{"ID":2,"NAME":"ABCD"}'

put table -name example1 -json '{"ID":3,"NAME":"ABCDDFR"}'

put table -name example1 -json '{"ID":4,"NAME":"AGRGE"}'

put table -name example1 -json '{"ID":5,"NAME":"DJIJOFKO"}'

put table -name example1 -json '{"ID":6,"NAME":"ABCDLLL"}'

 

get table -name example1      # non-ordered results of table scan #

{"ID":3,"NAME":"ABCDDFR"}

{"ID":6,"NAME":"ABCDLLL"}

{"ID":2,"NAME":"ABCD"}

{"ID":5,"NAME":"DJIJOFKO"}

{"ID":1,"NAME":"ABCDEF"}

{"ID":4,"NAME":"AGRGE"}

get table -name example1 -field NAME -end "ABCDZ"     # Specify the highest value to be returned #

{"ID":1,"NAME":"ABCDEF"}

{"ID":6,"NAME":"ABCDLLL"}

{"ID":2,"NAME":"ABCD"}

{"ID":3,"NAME":"ABCDDFR"}

put table -name example1 -json '{"ID":7,"NAME":"AB"}'    # Add another value #

get table -name example1 -field NAME -start "ABCD" -end "ABCDZ"   # Specific range of values to be returned #

{"ID":2,"NAME":"ABCD"}

{"ID":3,"NAME":"ABCDDFR"}

{"ID":1,"NAME":"ABCDEF"}

{"ID":6,"NAME":"ABCDLLL"}

 

Same example, using a Secondary Index:

exec "create table example (ID integer, NAME STRING, Primary Key (ID))"

exec "create index example_idx on example (NAME)"

put table -name example -json '{"ID":1,"NAME":"ABCDEF"}'

put table -name example -json '{"ID":2,"NAME":"ABCD"}'

put table -name example -json '{"ID":3,"NAME":"ABCDDFR"}'

put table -name example -json '{"ID":4,"NAME":"AGRGE"}'

put table -name example -json '{"ID":5,"NAME":"DJIJOFKO"}'

put table -name example -json '{"ID":6,"NAME":"ABCDLLL"}'

get table -name example     # non-ordered results of table scan #

{"ID":4,"NAME":"AGRGE"}

{"ID":6,"NAME":"ABCDLLL"}

{"ID":2,"NAME":"ABCD"}

{"ID":5,"NAME":"DJIJOFKO"}

{"ID":3,"NAME":"ABCDDFR"}

{"ID":1,"NAME":"ABCDEF"}

get table -name example -index example_idx      # ordered results of secondary index scan #

{"ID":2,"NAME":"ABCD"}

{"ID":3,"NAME":"ABCDDFR"}

{"ID":1,"NAME":"ABCDEF"}

{"ID":6,"NAME":"ABCDLLL"}

{"ID":4,"NAME":"AGRGE"}

{"ID":5,"NAME":"DJIJOFKO"}

get table -name example -index example_idx -field NAME -end "ABCDZ"

{"ID":2,"NAME":"ABCD"}

{"ID":3,"NAME":"ABCDDFR"}

{"ID":1,"NAME":"ABCDEF"}

{"ID":6,"NAME":"ABCDLLL"}

put table -name example -json '{"ID":7,"NAME":"AB"}'

get table -name example -index example_idx -field NAME -start "ABCD" -end "ABCDZ"

{"ID":2,"NAME":"ABCD"}

{"ID":3,"NAME":"ABCDDFR"}

{"ID":1,"NAME":"ABCDEF"}

{"ID":6,"NAME":"ABCDLLL"}

 

I hope that helps. From the Java API you would use the FieldRange class to specify the start/stop points.


我总结下字符串类型的FIeld的FieldRange查询。

备注:

字母的ascii值:

space(空格)为32;

A为65,此后字母递增;

a为97,此后字母递增。

现有name字段取以下值:
Oracle NoSQL学习的一点心得

Oracle NoSQL学习的一点心得

注意:从上面图片可以看出,以a开头的也检索出来了。【解释:因为a的ascii值大于A的】

Oracle NoSQL学习的一点心得

下面这个很有意思,需要注意下。【解释:因为'Abb'以A开头,而B得ascii值大于A】
Oracle NoSQL学习的一点心得


Oracle NoSQL学习的一点心得

Oracle NoSQL学习的一点心得

综上,结合实验可以看出,字符串的范围查询根据对应字符的ascii值来进行比较的。