作用和代价
上文介绍了关系型数据库里的索引。Notes数据库里的索引隐藏在视图概念里(本文的讨论仅仅针对Notes的视图索引,不包括全文索引。)。开发者创建的视图仅仅是存放在数据库里的一条设计文档。数据库引擎会根据它创建和更新索引。关系型数据库里的索引是从记录中抽取的数据排序而组成的数据结构(主要是B树),Notes视图的索引还包括未排序的列、计算值、分类、总计等等数据(数据结构仍然是B树,假设运气足够好的话,你会遇到Notes报出B-tree structure is invalid的错误)。用户在client里看到的视图就是索引的数据,再加上外观的设置。这种差别缘于两类数据库底层设计的差异。
关系型数据库里的索引是为了查询而建的。

SELECT NAME, JOB FROM PERSON WHERE COUNTRY='China'这样一个简单的查询语句,会由于PERSON表的COUNTRY列建有索引而大大提快速度。

而对SELECT * FROM PERSON这样无选择的查询语句,是否有索引则没有差别。作为文档型数据库的Notes。情况略有不同。文档型数据库里作为存储数据单元的文档,与关系型数据库里相应的记录相比最大的差异就是,文档没有记录受到的所在表定义的约束,比如一条记录有多少列,列的名称和数据类型是什么,长度几何等等。

每条文档都能够有随意数量、名称和数据类型的字段。假设说某个表里的每条记录都有一个共同的schema,那么能够说每条文档都有自己的schema。

在有些文档型数据库里,如大热的MongoDB。文档还被归类在表示同一种实体的collection里,有相似table的含义和用途。而在Notes数据库和还有一热门CouchDB里,连这种容器都没有,全部的文档,不管内容和用途是什么。都直接处于数据库这一级别之下(CouchDB与Notes数据库的相似之处还不仅这一点,考虑到它的最初作者Damien Katz就是来自Notes开发核心团队就一点都不奇怪了)。如此一来,即使是SELECT * FROM PERSON这样查询表格内全部数据的语句,在Notes里也没有直接的相应物了。这也意味着在Notes数据库里不论什么有意义的查询(也就是按文档的id查询之外)都必须藉助于视图这一概念。

由此可见,Notes视图索引的第一个作用是从数据库里选择某些文档,提取字段的值作为或计算列值。从而提供一个相似table的数据集合或接口。当我们在LotusScript或Java使用NotesView对象訪问当中的NotesViewEntry时,读取的就是索引。同一时候,文档的响应层次、分类、求和、平均值等功能又使得视图承担了关系型数据库里依靠SQL和其它方法实现的报表功能。

Notes视图索引第二个作用就是便于查找文档。经常使用的NotesView.GetAllDocumentsByKey和GetDocumentByKey的实质都是在索引里找到条目,再返回相应的文档。

用户在client展现的视图里排序、折叠展开分类以及按开头搜索,也都是利用索引完毕的。
Notes视图索引的代价和关系型数据库里讨论的一样,都是占领存储空间和消耗计算资源。
更新的时间
索引是何时建立的?又是何时更新的?从上一节对索引作用的讨论可知。展现文档集合和使用户能够快速查找文档,这两个至关重要的用途都要求索引的数据是最新的,也就是与它所基于的文档的数据是一致的。在上一篇文章里,我们提到理论上更新索引在时间上有三种选择,一是与文档改动(新增、改动和删除)同一时候,二是延迟至索引被读取时才检查是否须要更新,三是定时更新。选项一保证了索引与文档始终是一致的,可是加大了文档改动时数据库的负担。

选项二也能保证每次读取的索引是最新的。

与选项一相比优点是。在索引被读取前,相关的文档可能已经过多次改动。

不同用户改动不同文档,单个用户多次改动某个文档,等等各种情况都会发生。採用第一种方案时每次改动索引都须要更新,而方案二使得对索引两次被读取之间的全部改动(假设有)。仅仅需进行一次批量更新,从而降低开销。缺点是假设读取时发现索引须要更新,就添加了等待时间。第三种方案实际是对另外一种方案的补充,理念相同是批量更新,目的是降低读取索引时须要更新的次数和文档数量。
综合以上分析可见。採用方案一时用户訪问索引的速度是最快的。代价是所需系统资源也最多。方案二和三的延迟思路。节省了系统资源,但用户有时需忍受延时。关系型数据库基本上都採用第一种方案。

文档型数据库则选择各异。MongoDB採用方案一,CouchDB採用方案二,Notes则混合使用方案二和三。

更新的过程
定时更新
我们先来看Notes视图的定时更新。

这由server执行的Update和Updall两个任务来完毕。

两者的执行时间都能够在notes.ini里设置,默认情况下Update持续执行,Updall则在每天凌晨两点执行一次。Update维护两个队列(queue)。一个是即时队列(immediate queue),还有一个是延迟队列(deferred queue)。

队列里保存的是一条条某个数据库索引需更新的请求。请求的来源有几类:复制器(replicator)复制后假设某个副本的文档有变动。就会发送一条请求到队列。邮件路由器(router)将新消息派送到某个邮箱后也会发送一条请求。最频繁的则是一个用户在某个数据库里创建、改动或删除了文档,当他退出该数据库时。会发送一条请求到队列。

复制和用户改动产生的请求都被发送到延迟队列,特殊的比如触发数据库全文索引及时更新的操作会发送一条请求到即时队列。Update每隔五秒(能够通过notes.ini的UPDATE_IDLE_TIME和UPDATE_IDLE_TIME_MS设置改动此默认值,下同)检查两个队列,对即时队列里的请求立即处理。对延迟队列里的则会比較同一个数据库的请求,最先到达的请求之后的十五分钟(Update_Suppression_Time)内全部的请求都会被忽略。这样做还是为了降低资源的消耗。十五分钟以内对某个数据库的改动仅仅会触发Update更新其索引一次。
请求仅仅记录数据库的路径,Update在处理时先要推断对那些视图的索引进行更新。此时Notes再次显示了尽量节省资源的特性。

首先过去七天(UPDATE_ACCESS_FREQUENCY)内未被打开过的视图被忽略。接着根据索引上次更新时间和视图的选择条件搜索近期发生更改过的而且包括在该视图中的文档。假设数量少于二十(UPDATE_NOTE_MINIMUM),也不做更新。
Updall任务由于是在凌晨进行。Notes显得慷慨一些。它不管队列。而是检查全部数据库的全部视图,须要更新的更新,须要重建的重建。
打开时更新
定时更新不能保证索引被訪问时数据是最新的。仅仅能尽最大限度降低那时更新的负担。用户通过client界面或程序訪问视图时,会调用Notes API的NIFOpenCollection()函数打开索引(NIF意为Notes Indexing Facility。就是Notes索引部分的组件)。假设索引数据不是最新的。NIFOpenCollection()就会调用NIFUpdateCollection()更新索引。我们每次在client里打开一个视图时。都会发生这个过程(除非下面说明的特殊情况)。

假设距离上次Update更新该视图索引,发生更改的文档不多,这个过程就非常快能完毕。

而假设这期间有大量文档发生改动,甚至该视图的索引不存在,就须要等待非常长时间。

自R7后。Notes会在单独的后台线程中进行索引更新。用户界面因而不会被卡住,用户还能进行其它操作。

为了提高视图打开的速度,或者说最大程度地降低索引更新的次数。Notes视图里还有控制打开时是否更新的选项。


各自是:1. 自己主动。初次使用后。

2. 自己主动。3. 手动。

4. 自己主动。最多每n小时更新一次。手动意为打开视图时索引不自己主动更新,需按F9更新。

三种自己主动的差别在于,设为1或4时。假设一个视图未被打开过没有索引,Update和Updall执行时不会创建索引;设为2时则会;设为4时,假设索引在设置的近期n小时内被更新过,表现得就和设为3时一样。
索引在数据库里占领的空间不可小觑,数据库里假设视图多且复杂(列多,分类和排序多)。索引占领的空间甚至会超过文档的空间。所以视图里又有丢弃索引的设置,能够设为数据库关闭后或者未被訪问超过一定天数后丢弃。假设符合设置的条件。Updall任务负责删除索引。

所以,我们在设计视图时要……
每一个视图包括的索引有三类:
1.    依照NotesID排序的默认索引。
2.    依照某列排序的索引。
3.    父文档和子文档关系的索引。

每添加一个列排序(包括分类),就新增一个索引。多级分类比相同数量的排序须要的计算很多其它。

我们已经从上面的讨论看到Notes是怎样挖空心思地降低索引更新的次数,由于这是非常消耗计算资源的动作。在设计视图时,假设罔顾Notes的苦心。建一大堆用途不大的视图,又加上用户非常少使用的排序和必要性不大的分类,不但会导致Dominoserver上Update任务不堪重负。也会吞下视图打开缓慢的苦果。
曾经我曾提到,XPages视图层和数据层分开的优点之中的一个就是使视图能够仅仅作为数据集合,不同的展示须要。比方外观、列和文档的进一步筛选都能够利用XPages的视图控件实现。为降低视图数量提供了可能,从而也就降低了索引的数量。提高了性能和可维护性。
Notes帮助里实用的參考文章:
Notes Help - Refreshing view indexes
Administrator help - Indexer tasks: Update and Updall

84. 从视图索引说Notes数据库(下)的更多相关文章

  1. 83. 从视图索引说Notes数据库(上)

    索引是数据库系统重要的feature,不管是传统的关系型数据库还是时兴的NoSQL数据库,它攸关查询性能,因而在设计数据库时须要细加考量.然而,Lotus Notes隐藏技术底层.以用户界面为导向.追 ...

  2. Oracle数据库对象(表空间/同义词/序列/视图/索引)

    数据库对象 Oracle数据库对象: 数据库对象是数据库的组成部分,常常用 CREATE 命令进行创建,可以使用 ALTER 命令修改,用 DROP 执行删除操作. 种类: (1)表空间:所有的数据对 ...

  3. mysql中显示当前数据库下的所有表,包括视图。

    环境说明: mysql版本:5.5.57-log 操作系统:Red Hat Enterprise Linux Server release 6.6 (Santiago) 需求:查看当前数据库下所有的表 ...

  4. mysql中,查看当前数据库下所有的基表,不包括视图

    环境描述: mysql版本:5.5.57-log 操作系统版本:Red Hat Enterprise Linux Server release 6.6 (Santiago) 需求描述: 查看当前使用的 ...

  5. 第五章 MySQL事务,视图,索引,备份和恢复

    第五章 MySQL事务,视图,索引,备份和恢复 一.事务 1.什么是事务 事务是一种机制,一个操作序列,它包含了一组数据库操作命令,并且把所有的命令作为一个整体一起向系统提交或撤销操作请求.要么都执行 ...

  6. flask 在视图函数里操作数据库

    在视图函数里操作数据库 在视图函数里操作数据的方式和在python shell中的联系基本相同,只不过需要一些额外的工作.比如把查询结果作为参数 传入模板渲染出来,或是获取表单的字段值作为提交到数据库 ...

  7. oracle 序列 视图 索引 同义词

    序列 Oracle 12C 之后,Oracle 之中提供的是一种手工的自动增长列控制,而这样的控制在 Oracle 之中使用序列(对象)完成. 序列的创建: CREATE SEQUENCE 序列名称 ...

  8. Oracle学习2 视图 索引 sql编程 游标 存储过程 存储函数 触发器

    ---视图 ---视图的概念:视图就是提供一个查询的窗口,来操作数据库中的数据,不存储数据,数据在表中. ---一个由查询语句定义的虚拟表. ---查询语句创建表 create table emp a ...

  9. Django基础--Django基本命令、路由配置系统(URLconf)、编写视图、Template、数据库与ORM

    web框架 框架,即framework,特指为解决一个开放性问题而设计的具有一定约束性的支撑结构. 使用框架可以帮你快速开发特定的系统. 简单地说,就是你用别人搭建好的舞台来做表演. 尝试搭建一个简单 ...

随机推荐

  1. C++_知识点_结构体/枚举/联合

    //C++中结构体的不同之处 #include <iostream> #include <string> using namespace std; int main(void) ...

  2. ExpandableListView 箭头样式

    ExpandableListVivew是ListView的子类,它在普通ListView的基础上进行了扩展,它把应用中的列表项分为几组,每组里 又可包含多个列表项.ExpandableListVive ...

  3. Gulp 从0开始

    http://www.w3ctech.com/topic/134  (该文章有很多错误) http://markpop.github.io/2014/09/17/Gulp%E5%85%A5%E9%97 ...

  4. semver语义化版本号

    semver语义化版本号 语义化版本号各位置的含义 版本号:X.Y.Z X: 代表发生了不兼容的API改变 Y: 代表向后兼容的功能性变化 Z: 代表向后兼容bug fixes 语义化版本号示例 1. ...

  5. cocos2dx mac环境搭建

    1)下载cocos2dx 2.2.3并解压

  6. BZOJ 1103 [POI2007]大都市meg(树状数组+dfs序)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1103 [题目大意] 给出一棵树,每条边的经过代价为1,现在告诉你有些路不需要代价了, ...

  7. java的数学函数总结

    java的数学函数都放在java.lang这个包中,并且这些函数的方法在类Math中是作为static方法出现的,所以要引用一个特定的函数,只需将类Math和一个圆点写在要使用的方法前就好.如方法sq ...

  8. 假设给Contact的List加一个用字母排序的导航

    效果图: 这样写Layout: <? xml version="1.0" encoding="utf-8"? > <LinearLayout ...

  9. ZOJ 38727(贪心)

    这道题真心坑.越想越远  想的飞起来了. 最后纠结起后缀表达式的定义来了. 题意: 就是给你一个串 ,  让你用最少改动次数来实它变成一个合法的后缀表达式,  改动方式有两种, 一种是直接加入数字或者 ...

  10. SSDP协议的Android实现以及使用

    前面一篇博客里面已经介绍过SSDP协议原理,本篇博客将实现实现Android上的SSDP协议. 关键技术分析:1.发送广播:须要发送送广播,所以须要使用MulticastSocket.SocketAd ...