热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Indexes:RDBMSvsCoherencevsLucene

大家都熟悉SQL数据库中索引的概念.但除了关系数据库,索引被广泛应用于更多的领域.包括很多专有的产品,例如搜索引擎.搜索引擎会用到索引来划分数据.本文将在三种不同技术中索引的功能和

大家都熟悉SQL数据库中索引的概念. 但除了关系数据库, 索引被广泛应用于更多的领域. 包括很多专有的产品,例如搜索引擎. 搜索引擎会用到索引来划分数据. 本文将在三种不同技术中索引的功能和性能方面给出一个大概的比较. 这三种技术分别为: SQL数据库, 内存网格(Oracle Coherence)和全文检索引擎(Apache Lucene)

多条件查询

当面对大量数据时我们经常需要根据一些条件选出子集来. 例如股票交易或者网上交易记录. 一个简单的例子,找出所有26码的女鞋. SQL语句类似:

select * from product where type=’shoes’, color=’red’, size=’26’, gender=’W’

下面我们用这个查询来比较不同技术实现.

倒排索引

相信大家都熟悉到排索引, 不过这里还是简单的解释下. 到排索引背后的概念很简单, 也被运用在本文介绍的三种技术中.想像我们有条记录包括了A,B,C三个字段. 我们想这样的查询”select * from records where A=x”. 为了避免全表扫描,我们会创建额外的结构(索引)来记录A字段每个值所对应的所有记录.


所以如果我们需要A=1的所有记录, 只需要在A索引中找到1记录, 就会得到符合条件的所有记录列表. 看起来很简单,但理想是天使,细节是恶魔. 如何来存储索引? 如何处理多条件查询? 不同技术有不同的答案,而这些答案对查询性能有巨大的影响.

RDBMS – 基于BTree的倒排索引

BTree是在关心数据库中倒排索引最普遍的实现(也许有其他的实现但我们这次先只关注BTrees). BTree适用于磁盘存储,已经在关系数据库中应用了几十年. 典型的SQL数据库容许你在一个或多个字段上创建索引, 一张表可以创建多个索引. 如果要创建在多个字段上创建复合索引, 字段的顺序很重要.

正常情况下关系数据库在查询时只用到某表的一个BTree索引. 这是很关键的一点!

那么关系数据库如何处理上面那个关于鞋的查询呢? 数据库必须选择一个最佳索引(通常是根据统计). 数据库会用这个索引来选出查询结果的超集,然后用剩下的查询条件来过滤这个超集. 例如数据库可能选择颜色字段来作为最佳索引, 然后会用这个索引查出所有红色的产品, 接下来再在此结果上筛去不是26码的男鞋. 也就是说及时用到索引数据库仍然还有很多工作要做. 事实上这个例子对于数据库来说是个很低效的. 无论数据库选择那个单独字段作索引,都极有可能需要检查上千条记录才能完成查询.不过还是比全表扫描要好些.

有没有可能多条件查询时更有效的使用索引呢? 答案当然是肯定的.

我们可以创建符合索引, 例如尺寸和颜色. 使用这样的索引数据库就能仅仅扫描所有红色,尺寸为26码的产品. 这样我们只需要扫描少量的结果. 我们可以在数据库里调整索引来满足我们特定的查询. 但是上面这个复合索引对于其它查询,例如另外一个尺寸的红色女鞋是没有效果的.

更新: 尽管BTree索引在关系数据库中被广泛使用,但他们不是唯一的选择. 一些数据库,例如Oracle,可以使用位图索引(类似Lucence,详见下文). Oracle也能做BTree索引交集操作(类似Coherence),尽管查询分析器很少采用这个策略.

内存网格中的索引

内存网格数据也可以使用索引来提高查询的性能. 网格通常采用内存数据结构(哈希表或排序树),而不是BTree. 以Oracle Coherence为例. 在Coherence中(包括一般的数据网格)数据是分布在多个集群节点上(processes participating in grid), 每个对象都有自己的节点. 索引可是跨节点分布的;每个节点负责自己节点上数据的索引.

当在Coherence上查询, 查询会被广播到所用节点上,每个节点在自己本地数据上执行查询操作,然后返回结果集. 所有节点的结果集最后被合并成最后的查询结果.

每个节点只存储所有数据的一部分,而所有这些数据都在内存中而不是磁盘上. 所以和关系数据相比,网格采用稍微不同的方法来使用索引. 不像关系数据库, Coheren能用多个索引来执行一个简单的查询.

回到最初的例子上. 假设我们在不同的字段上都建有索引, Coherence能取回多个结果接,包括"所有的鞋","所有的红鞋","所有的女鞋","所有的26码鞋"(每个对应不同的字段索引). 这里重要的一点是Coherence只要查询中每个字段都有索引,就不必自己检查每个对象. 在Coherence索引上的对象集的实现都是哈希集(使用对象的主键来引用对象).为了选出两个哈希集的交集,Coherence必须轮询其中一个结合然后和另外一个结合做比较.如果一个集合很小,则查询会非常快. 但如果两个结果都有上千条纪录则会花很多的时间.

这个方法也有局限性. 在上述的例子中,所有4个集合产生的索引会很多,所以求交集的操作会很费时间. 有时不用索引反而会提高查询性能(例如女鞋的结果集很大时). 查询条件(Coherence中叫做filter)的顺序也很重要,因为Coherence不会做全局的查询优化. 不过这个方法一般会比数据库的多条件查询要好, 但这个查询例子还不是特别适合内存数据网格.

Lucence的位图索引

Lucene是个java实现的全文文本搜索引擎. 惊喜的是全文本搜索和多条件查询十分类似. Lucene可以直接处理我们的查询. 

Lucene使用压缩的位图来储存倒排索引(即不是BTress也不是哈希表).压缩位图有两个重要的特性: 1,更小的空间2,可以不解压缩做binary operations(例如求交集). 类似Coherence, Lucene可以使用所有的四个索引来做查询.但是不像Coherence,使用了压缩位图的Lucene可以很快的处理Coherence提到的四个集合的交集操作.即使每个集合都上千条纪录也是小菜一碟.

使用压缩位图让Lucene是处理多条件查询的强力工具,在实践中Lucene能够比数据库或是Coherence处理此类型查询要快上个数量级.

但是使用位图也有代价. 实践中压缩位图的更新需要重写整个集合. 这意味着基于位图索引的更新操作代价是极高的. Lucene正在花大力气改进这个根本性的局限点.(例如索引分段和logarithmic merging under hood), 但是Lucenne的索引更新代价通常还是要比数据库和Coherence要高.

最佳组合:

如果你正在使用Coherence并且羡慕Lucene的搜索能力,你可以尝试grid4search项目.其容许使用Lucene替换Coherence内置索引.



原文出处:http://blog.griddynamics.com/2011/04/indexes-rdbms-vs-coherence-vs-lucene.html


推荐阅读
author-avatar
书友53034809
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有