<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Oracle Berkeley DB 中国研发团队的博客 &#187; Berkeley DB</title>
	<atom:link href="http://www.bdbchina.com/category/berkeley-db/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.bdbchina.com</link>
	<description>Oracle Berkeley DB 中国研发团队的博客</description>
	<lastBuildDate>Thu, 15 Dec 2011 10:35:52 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Oracle Berkeley Database 11g R2  性能概述白皮书</title>
		<link>http://www.bdbchina.com/2011/09/oracle-berkeley-database-11g-r2-%e6%80%a7%e8%83%bd%e6%a6%82%e8%bf%b0%e7%99%bd%e7%9a%ae%e4%b9%a6/</link>
		<comments>http://www.bdbchina.com/2011/09/oracle-berkeley-database-11g-r2-%e6%80%a7%e8%83%bd%e6%a6%82%e8%bf%b0%e7%99%bd%e7%9a%ae%e4%b9%a6/#comments</comments>
		<pubDate>Wed, 07 Sep 2011 10:05:22 +0000</pubDate>
		<dc:creator>mingxingchen</dc:creator>
				<category><![CDATA[Berkeley DB]]></category>
		<category><![CDATA[Mingxing Chen]]></category>
		<category><![CDATA[bdb]]></category>
		<category><![CDATA[performance]]></category>

		<guid isPermaLink="false">http://www.bdbchina.com/?p=1698</guid>
		<description><![CDATA[这是一篇由我翻译的文章，现在贴过来，与大家共享。原文可以从BDB官网下载得到， 请见：http://www.oracle.com/us/dm/bdb-performance-whitepaper-cn-426008-zhs.pdf。
==============================================================

概述
当选择一个数据库时，其性能的好坏往往是我们要考虑的第一关键因素。本白皮书介绍了一些性能测定的方法，旨在帮助你理解从Berkeley DB 数据库的一些常见配置预期会得到怎样的性能。你的应用程序的性能也取决于你的数据、数据访问的模式、缓存大小、其他配置参数、操作系统、以及硬件等。基准测试并不能反映某一个特定的应用程序的性能好坏，但它们可以提供一些基准，并为建立基本可行的期望提供指导和帮助。

介绍
通过一些在一定配置下进行的测试，本文给出了有关Oracle Berkeley DB (BDB) 11gR2 (11.2.5.0.2.21) 吞吐量的信息。这些测试包括：不同配置下BDB 键/值接口 (key/value API) 得到的吞吐量，和使用Wisconsin 和类TPC-B 基准对BDB SQL接口进行测试得到的性能数据。
实验环境
所有的实验结果都是用相同的硬件配置得到的，硬件信息如表1所示：
表1. 硬件配置



处理器
操作系统
RAM
硬盘及速度
文件系统


Intel 酷睿2双核 E8400, 3.0GHz
Redhat Linux 5.4
4GB
SATA, 7200 RPM
EXT3



键/值接口的性能概述
Berkeley DB 是高可配置的，它可以配置来使用或禁止数据库操作的大多数特性，例如，事务日志（WAL）功能，并发控制的锁机制。由于这个原因，Berkeley DB 将在两种不同配置环境下进行实验：分别对应于非事务性及事务性。
第一组实验测试数据存储Data Store(DS)。DS是Berkeley DB的配置选项之一。DS本质上是一种简单的、单线程、非事务性的存储系统。第二组实验测试事务性数据存储Transactional Data Store(TDS)。TDS是Berkeley DB的一种能提供所有事务语义(transactional semantics)的配置选项。表2给出这两种功能集的区别。
表2. 数据存储与事务性数据存储属性



特点
数据存储（DS）
事务性数据存储（TDS）


访问方法（Access Method）
B树
B树


锁（locking）
无
页级锁


日志（logging）
无
带有128MB缓存的磁盘


事务（transactions）
无
同步（Synchronous）


共享内存（Shared Memory）
不共享（DB_PRIVATE）
不共享（DB_PRIVATE）


缓存
512MB
512MB



这两组实验都使用512MB的缓存，在数据库环境中设置DB_PRIVATE的标志，同时空间局部值（spatial locality）设为10。使用DB_PRIVATE标志说明在数据库中使用堆内存（heap memory）作为其高速缓存（cache），这种配置只适用于单进程（可能有多个线程）的环境中执行。
最常用的数据库性能衡量标准是吞吐量（就是在固定时间段里读取或写入的记录数）。在我们的实验中，我们把吞吐量定义为是用Berkeley DB11gR2 (版本号为11.2.5.0.21)每秒能达到的操作次数。
在实验中，我们使用固定长度的记录。每条记录包括64字节的键值（key）和64字节的数据值（data）。所有的键值和数据值均为整数型。每个实验进行57,600批次，每个批次对应10个顺序的键值操作。比如，在插入测试中，随机产生第一个键的值（记住k），并对它进行插入操作；接下来再插入9个记录， 这9个记录具有连续的键值（k+1, k+2, k+3, …, k+9）；这个过程将重复57,600次。每个测试都运行5次，并记录相应的吞吐量的平均值和标准差。
针对每个配置，下面是实验的步骤：

步骤一：

生成一个具有576,000条记录的数据库（就是57,600组，每组具有10个顺序键值的记录）。这个过程仅仅是生成用于实验的数据库和预热缓存，测试并不记录其消耗的时间。

步骤二：

检索57,600个随机记录组，每组具有10个连续键值的记录（读取操作）。

步骤三：

更新57,600个随机记录组，每组具有10个连续键值的记录（更新操作）。

步骤四：

删除数据库中的所有记录，以每组具有10个连续键值的记录为单位（删除操作）。

步骤五：

像步骤一那样，重新生成测试的数据库（插入操作）。
针对每一个类型的操作（读取、更新、删除、插入），计时从第一个组操作前开始直到完成最后一组操作结束。这期间不包括用于打开和关闭数据库环境和数据库句柄所花的时间。
数据存储：单线程
第一组实验是衡量使用Berkeley DB DS来测试单线程应用程序所达到的吞吐量。表3是实验得到的结果。
表3. BDB DS 单线程的性能



描述
插入(Insert)
读取(Fetch)
删除(Delete)
更新(Update)


操作数/秒
标准差
操作数/秒
标准差
操作数/秒
标准差
操作数/秒
标准差


DS
208,139
329
264,665
229
158,506
236
250,297
870



事务性数据存储：单线程
第二组实验统计了基于Berkeley DB TDS的单线程应用程序在不同的配置下所达到的吞吐量。这些配置包括：写持久性，日志持久性，和存储介质。每个配置将解释为：

 写持久性

默认条件下，事务将被同步提交到磁盘。设置DB_TXN_NOSYNC标志将意味着异步提交（即数据不会同步到磁盘），而DB_TXN_WRITE_NOSYNC标志意味着把数据写入到文件系统但不会同步到磁盘。

日志持久性

默认测试，日志是存储在磁盘中；同时也测试了非持久的、内存中的日志信息。

不同的存储介质

默认的配置是采用一个传统的硬盘。我们将比较使用这种默认配置和使用2GB的RAM在存储数据库和日志文件方面得到的性能。在所有的情况下，事务都会同步提交。
表4. [...]]]></description>
			<content:encoded><![CDATA[<p><em><em>这是一篇由我翻译的文章，现在贴过来，与大家共享。原文可以从BDB官网</em>下载得到， 请见：http://www.oracle.com/us/dm/bdb-performance-whitepaper-cn-426008-zhs.pdf<em>。</em></em></p>
<p><em>==============================================================<br />
</em></p>
<h1>概述</h1>
<p>当选择一个数据库时，其性能的好坏往往是我们要考虑的第一关键因素。本白皮书介绍了一些性能测定的方法，旨在帮助你理解从Berkeley DB 数据库的一些常见配置预期会得到怎样的性能。你的应用程序的性能也取决于你的数据、数据访问的模式、缓存大小、其他配置参数、操作系统、以及硬件等。基准测试并不能反映某一个特定的应用程序的性能好坏，但它们可以提供一些基准，并为建立基本可行的期望提供指导和帮助。</p>
<h1><span id="more-1698"></span></h1>
<h1>介绍</h1>
<p>通过一些在一定配置下进行的测试，本文给出了有关Oracle Berkeley DB (BDB) 11gR2 (11.2.5.0.2.21) 吞吐量的信息。这些测试包括：不同配置下BDB 键/值接口 (key/value API) 得到的吞吐量，和使用Wisconsin 和类TPC-B 基准对BDB SQL接口进行测试得到的性能数据。</p>
<h1>实验环境</h1>
<p>所有的实验结果都是用相同的硬件配置得到的，硬件信息如表1所示：</p>
<p>表1. 硬件配置</p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top">处理器</td>
<td valign="top">操作系统</td>
<td valign="top">RAM</td>
<td valign="top">硬盘及速度</td>
<td valign="top">文件系统</td>
</tr>
<tr>
<td valign="top">Intel 酷睿2双核 E8400, 3.0GHz</td>
<td valign="top">Redhat Linux 5.4</td>
<td valign="top">4GB</td>
<td valign="top">SATA, 7200 RPM</td>
<td valign="top">EXT3</td>
</tr>
</tbody>
</table>
<h1>键/值接口的性能概述</h1>
<p>Berkeley DB 是高可配置的，它可以配置来使用或禁止数据库操作的大多数特性，例如，事务日志（WAL）功能，并发控制的锁机制。由于这个原因，Berkeley DB 将在两种不同配置环境下进行实验：分别对应于非事务性及事务性。</p>
<p>第一组实验测试数据存储Data Store(DS)。DS是Berkeley DB的配置选项之一。DS本质上是一种简单的、单线程、非事务性的存储系统。第二组实验测试事务性数据存储Transactional Data Store(TDS)。TDS是Berkeley DB的一种能提供所有事务语义(transactional semantics)的配置选项。表2给出这两种功能集的区别。</p>
<p>表2. 数据存储与事务性数据存储属性</p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="189" valign="top">特点</td>
<td width="189" valign="top">数据存储（DS）</td>
<td width="189" valign="top">事务性数据存储（TDS）</td>
</tr>
<tr>
<td width="189" valign="top">访问方法（Access Method）</td>
<td width="189" valign="top">B树</td>
<td width="189" valign="top">B树</td>
</tr>
<tr>
<td width="189" valign="top">锁（locking）</td>
<td width="189" valign="top">无</td>
<td width="189" valign="top">页级锁</td>
</tr>
<tr>
<td width="189" valign="top">日志（logging）</td>
<td width="189" valign="top">无</td>
<td width="189" valign="top">带有128MB缓存的磁盘</td>
</tr>
<tr>
<td width="189" valign="top">事务（transactions）</td>
<td width="189" valign="top">无</td>
<td width="189" valign="top">同步（Synchronous）</td>
</tr>
<tr>
<td width="189" valign="top">共享内存（Shared Memory）</td>
<td width="189" valign="top">不共享（DB_PRIVATE）</td>
<td width="189" valign="top">不共享（DB_PRIVATE）</td>
</tr>
<tr>
<td width="189" valign="top">缓存</td>
<td width="189" valign="top">512MB</td>
<td width="189" valign="top">512MB</td>
</tr>
</tbody>
</table>
<p>这两组实验都使用512MB的缓存，在数据库环境中设置DB_PRIVATE的标志，同时空间局部值（spatial locality）设为10。使用DB_PRIVATE标志说明在数据库中使用堆内存（heap memory）作为其高速缓存（cache），这种配置只适用于单进程（可能有多个线程）的环境中执行。</p>
<p>最常用的数据库性能衡量标准是吞吐量（就是在固定时间段里读取或写入的记录数）。在我们的实验中，我们把吞吐量定义为是用Berkeley DB11gR2 (版本号为11.2.5.0.21)每秒能达到的操作次数。</p>
<p>在实验中，我们使用固定长度的记录。每条记录包括64字节的键值（key）和64字节的数据值（data）。所有的键值和数据值均为整数型。每个实验进行57,600批次，每个批次对应10个顺序的键值操作。比如，在插入测试中，随机产生第一个键的值（记住k），并对它进行插入操作；接下来再插入9个记录， 这9个记录具有连续的键值（k+1, k+2, k+3, …, k+9）；这个过程将重复57,600次。每个测试都运行5次，并记录相应的吞吐量的平均值和标准差。</p>
<p>针对每个配置，下面是实验的步骤：</p>
<ul>
<li><strong>步骤一：</strong></li>
</ul>
<p>生成一个具有576,000条记录的数据库（就是57,600组，每组具有10个顺序键值的记录）。这个过程仅仅是生成用于实验的数据库和预热缓存，测试并不记录其消耗的时间。</p>
<ul>
<li><strong>步骤二：</strong></li>
</ul>
<p>检索57,600个随机记录组，每组具有10个连续键值的记录（读取操作）。</p>
<ul>
<li><strong>步骤三：</strong></li>
</ul>
<p>更新57,600个随机记录组，每组具有10个连续键值的记录（更新操作）。</p>
<ul>
<li><strong>步骤四：</strong></li>
</ul>
<p>删除数据库中的所有记录，以每组具有10个连续键值的记录为单位（删除操作）。</p>
<ul>
<li><strong>步骤五：</strong></li>
</ul>
<p>像步骤一那样，重新生成测试的数据库（插入操作）。</p>
<p>针对每一个类型的操作（读取、更新、删除、插入），计时从第一个组操作前开始直到完成最后一组操作结束。这期间不包括用于打开和关闭数据库环境和数据库句柄所花的时间。</p>
<h2>数据存储：单线程</h2>
<p>第一组实验是衡量使用Berkeley DB DS来测试单线程应用程序所达到的吞吐量。表3是实验得到的结果。</p>
<p>表3. BDB DS 单线程的性能</p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td rowspan="2" width="42" valign="top">描述</td>
<td colspan="2" width="132" valign="top">插入(Insert)</td>
<td colspan="2" width="131" valign="top">读取(Fetch)</td>
<td colspan="2" width="131" valign="top">删除(Delete)</td>
<td colspan="2" width="131" valign="top">更新(Update)</td>
</tr>
<tr>
<td width="76" valign="top">操作数/秒</td>
<td width="56" valign="top">标准差</td>
<td width="76" valign="top">操作数/秒</td>
<td width="56" valign="top">标准差</td>
<td width="76" valign="top">操作数/秒</td>
<td width="56" valign="top">标准差</td>
<td width="76" valign="top">操作数/秒</td>
<td width="56" valign="top">标准差</td>
</tr>
<tr>
<td width="42" valign="top">DS</td>
<td width="76" valign="top">208,139</td>
<td width="56" valign="top">329</td>
<td width="76" valign="top">264,665</td>
<td width="56" valign="top">229</td>
<td width="76" valign="top">158,506</td>
<td width="56" valign="top">236</td>
<td width="76" valign="top">250,297</td>
<td width="56" valign="top">870</td>
</tr>
</tbody>
</table>
<h2>事务性数据存储：单线程</h2>
<p>第二组实验统计了基于Berkeley DB TDS的单线程应用程序在不同的配置下所达到的吞吐量。这些配置包括：写持久性，日志持久性，和存储介质。每个配置将解释为：</p>
<ul>
<li><strong><span style="text-decoration: underline;"> 写持久性</span></strong></li>
</ul>
<p>默认条件下，事务将被同步提交到磁盘。设置DB_TXN_NOSYNC标志将意味着异步提交（即数据不会同步到磁盘），而DB_TXN_WRITE_NOSYNC标志意味着把数据写入到文件系统但不会同步到磁盘。</p>
<ul>
<li><strong><span style="text-decoration: underline;">日志持久性</span></strong></li>
</ul>
<p>默认测试，日志是存储在磁盘中；同时也测试了非持久的、内存中的日志信息。</p>
<ul>
<li><strong><span style="text-decoration: underline;">不同的存储介质</span></strong></li>
</ul>
<p>默认的配置是采用一个传统的硬盘。我们将比较使用这种默认配置和使用2GB的RAM在存储数据库和日志文件方面得到的性能。在所有的情况下，事务都会同步提交。</p>
<p>表4. BDB单线程性能</p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td rowspan="2" width="89" valign="top">描述</td>
<td colspan="2" width="118" valign="top">插入(Insert)</td>
<td colspan="2" width="124" valign="top">读取(Fetch)</td>
<td colspan="2" width="118" valign="top">删除(Delete)</td>
<td colspan="2" width="118" valign="top">更新(Update)</td>
</tr>
<tr>
<td width="68" valign="top">操作数/秒</td>
<td width="50" valign="top">标准差</td>
<td width="71" valign="top">操作数/秒</td>
<td width="53" valign="top">标准差</td>
<td width="69" valign="top">操作数/秒</td>
<td width="50" valign="top">标准差</td>
<td width="69" valign="top">操作数/秒</td>
<td width="50" valign="top">标准差</td>
</tr>
<tr>
<td width="89" valign="top">TDS SYNC</td>
<td width="68" valign="top">693</td>
<td width="50" valign="top">10</td>
<td width="71" valign="top">159,837</td>
<td width="53" valign="top">895</td>
<td width="69" valign="top">831</td>
<td width="50" valign="top">23</td>
<td width="69" valign="top">1,732</td>
<td width="50" valign="top">18</td>
</tr>
<tr>
<td width="89" valign="top">TDS RAMDISK<sup>1</sup></td>
<td width="68" valign="top">49,673</td>
<td width="50" valign="top">912</td>
<td width="71" valign="top">162,848</td>
<td width="53" valign="top">1,588</td>
<td width="69" valign="top">44,279</td>
<td width="50" valign="top">277</td>
<td width="69" valign="top">60,973</td>
<td width="50" valign="top">291</td>
</tr>
<tr>
<td width="89" valign="top">TDS WNS<sup>2</sup></td>
<td width="68" valign="top">37,664</td>
<td width="50" valign="top">460</td>
<td width="71" valign="top">160,307</td>
<td width="53" valign="top">293</td>
<td width="69" valign="top">36,110</td>
<td width="50" valign="top">454</td>
<td width="69" valign="top">52,922</td>
<td width="50" valign="top">258</td>
</tr>
<tr>
<td width="89" valign="top">TDS NS<sup>3</sup></td>
<td width="68" valign="top">53,199</td>
<td width="50" valign="top">613</td>
<td width="71" valign="top">159,980</td>
<td width="53" valign="top">1,419</td>
<td width="69" valign="top">49,340</td>
<td width="50" valign="top">183</td>
<td width="69" valign="top">86,960</td>
<td width="50" valign="top">639</td>
</tr>
<tr>
<td width="89" valign="top">TDS INMEM<sup>4</sup></td>
<td width="68" valign="top">66,435</td>
<td width="50" valign="top">102</td>
<td width="71" valign="top">163,229</td>
<td width="53" valign="top">815</td>
<td width="69" valign="top">58,845</td>
<td width="50" valign="top">101</td>
<td width="69" valign="top">97,602</td>
<td width="50" valign="top">396</td>
</tr>
</tbody>
</table>
<p>1 2GB RAMDISK, 数据库和日志均存在RAM磁盘中</p>
<p>2 DB_TXN_WRITE_NOSYNC，事务提交时设置的标志</p>
<p>3 DB_TXN_NOSYNC，事务提交时设置的标志</p>
<p>4允许在内存中存储日志</p>
<p>在所有的实验中，我们使用足够大的缓存大小，所以磁盘的I/O操作并不影响读的吞吐量。通过对比TDS和TDS RAMDISK的结果，不难发现磁盘的I/O延时和性能会大大影响写操作。通过比较TDS SYNC, TDS INMEM, TDS WNS 和 TDS NS的结果，我们可以发现不同的持久性设置也会影响到写的吞吐量。</p>
<p>上述结果显示了对数据库来说很常见的一些有趣特点。其中一个特点是I/O是决定数据库性能好坏的最关键因素。I/O操作尽管对数据库的读操作来说，仅会造成较小影响，但却是决定写操作性能的关键原因。在使用TDS进行的实验中，插入和更新操作会导致大量的I/O操作，所以在性能上会受到很大的影响。</p>
<p>这些实验表明了五种主要类别造成的延迟：</p>
<ul>
<li> 内存和处理器</li>
</ul>
<ul>
<li>从用户到内核空间之间的传递</li>
</ul>
<ul>
<li>文件系统</li>
</ul>
<ul>
<li>存储I / O</li>
</ul>
<ul>
<li>介质</li>
</ul>
<p>TDS INMEM的实验是最快速的，因为所有的事务提交到内存的数据缓冲区，没有把数据转入到文件系统缓冲区或是磁盘所带来的开销。使用TDS INMEM单线程进行插入操作的实验为你的系统显示了最理想的速度，但是可能不是很有用，原因是此时数据不具有永久性。在进程意外结束时，内存中的数据将会被删除掉，所有没有持久性可言。</p>
<p>当事务配置了DB_TXN_NOSYNC标志时，在事务提交时，数据是不会从日志缓存区提交或同步到文件系统的。相反，日志会被保留在日志缓存区中直到该缓存满为止，此时一个文件系统的写操作会把日志从用户内存传输到内核或是文件系统内存中。接下来，由文件系统自己决定数据是否要写进以及何时写进磁盘介质中。所以，在TDS INMEM和TDS NS之间的不同性能正好反映了当日志缓存区满时把日志记录从用户级别的日志缓存区传输到内核或是文件系统内存所带来的开销。</p>
<p>当事务配置了DB_TXN_WRITE_NOSYNC标志时，Berkeley DB在每个事务提交时都会把日志从用户级别的日志缓存区提交或同步到操作系统或是文件系统。这样只要在把数据写到磁盘之前该操作系统不挂掉，就能提供持久性的保证，。因此，在应用程序挂掉时，只要操作系统能继续在运行的话，数据就不会丢失。但是，如果此时操作系统或是硬件也挂掉的话，已写入操作系统但没有写入磁盘的数据将会被丢失。</p>
<p>在TDS WNS和TD SNS的实验中，插入操作得到的不同结果就是反映了把日志从Berkeley DB日志缓存区拷到文件系统时造成事务提交的时间上的差别。最后，通过对比TDS SYNC和TDS RAMDISK的结果，你就会观察到往内存中写和往磁盘上写带来的性能差别。在TDS SYNC这个实验中，SATA总线和硬盘驱动带来的开销会大大降低性能。</p>
<p>相当有趣的是，在所有的实验中，读操作的性能基本上是一致，平均值占标准差只有1%（标准差=1655.92，平均=161240.2，百分比=1.026989482）。这说明了在所有的实验中，缓存造成的影响是一样的，因此在对内存中的数据进行读操作时带来的事务开销是可以忽略不计的。 尽管没有统计，但是I/O操作的开销决定了对在缓存外的数据进行读操作所需要的时间。</p>
<h2>事务性数据存储：扩展对称多处理系统</h2>
<p>下表显示的是BDB TDS在对称多处理系统（SMPs）时性能的数据。针对多线程访问，每个线程都使用一个数据库句柄（DB handle）以减少线程间的竞争。每个线程使用一个计时器来计算其吞吐量。下表显示的是所有这些信息的集合。</p>
<p>当引入第二个线程时，每个操作的吞吐量将相应地减少，原因是系统将进行一些锁操作，所以会导致一些相应的开销。总体上来说，写操作的吞吐量将随着线程数加大而呈按比例递增。但是，当读线程超过4个的时候，读操作的吞吐量将下降，原因是此时CPU的利用率是100%，而额外的线程需要一些不必要的上下文交互和硬件缓存的回收。</p>
<p>表5. 在SMP系统上，配置不同线程数对应的TDS性能</p>
<table border="1" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td rowspan="2" width="15%" valign="top">描述</td>
<td colspan="2" width="20%" valign="top">插入(Insert)</td>
<td colspan="2" width="21%" valign="top">读取(Fetch)</td>
<td colspan="2" width="21%" valign="top">删除(Delete)</td>
<td colspan="2" width="21%" valign="top">更新(Update)</td>
</tr>
<tr>
<td width="11%" valign="top">操作数/秒</td>
<td width="8%" valign="top">标准差</td>
<td width="12%" valign="top">操作数/秒</td>
<td width="9%" valign="top">标准差</td>
<td width="12%" valign="top">操作数/秒</td>
<td width="8%" valign="top">标准差</td>
<td width="12%" valign="top">操作数/秒</td>
<td width="9%" valign="top">标准差</td>
</tr>
<tr>
<td width="15%" valign="top">TDS 1个线程</td>
<td width="11%" valign="top">693</td>
<td width="8%" valign="top">10</td>
<td width="12%" valign="top">159,837</td>
<td width="9%" valign="top">895</td>
<td width="12%" valign="top">831</td>
<td width="8%" valign="top">23</td>
<td width="12%" valign="top">1,732</td>
<td width="9%" valign="top">18</td>
</tr>
<tr>
<td width="15%" valign="top">TDS 2个线程</td>
<td width="11%" valign="top">647</td>
<td width="8%" valign="top">7</td>
<td width="12%" valign="top">106,196</td>
<td width="9%" valign="top">432</td>
<td width="12%" valign="top">767</td>
<td width="8%" valign="top">20</td>
<td width="12%" valign="top">1,634</td>
<td width="9%" valign="top">27</td>
</tr>
<tr>
<td width="15%" valign="top">TDS 3个线程</td>
<td width="11%" valign="top">690</td>
<td width="8%" valign="top">9</td>
<td width="12%" valign="top">126,762</td>
<td width="9%" valign="top">762</td>
<td width="12%" valign="top">863</td>
<td width="8%" valign="top">20</td>
<td width="12%" valign="top">1,909</td>
<td width="9%" valign="top">32</td>
</tr>
<tr>
<td width="15%" valign="top">TDS 4个线程</td>
<td width="11%" valign="top">721</td>
<td width="8%" valign="top">8</td>
<td width="12%" valign="top">134,581</td>
<td width="9%" valign="top">497</td>
<td width="12%" valign="top">882</td>
<td width="8%" valign="top">18</td>
<td width="12%" valign="top">2,085</td>
<td width="9%" valign="top">54</td>
</tr>
<tr>
<td width="15%" valign="top">TDS 8个线程</td>
<td width="11%" valign="top">859</td>
<td width="8%" valign="top">26</td>
<td width="12%" valign="top">128,928</td>
<td width="9%" valign="top">423</td>
<td width="12%" valign="top">967</td>
<td width="8%" valign="top">27</td>
<td width="12%" valign="top">2,497</td>
<td width="9%" valign="top">32</td>
</tr>
<tr>
<td width="15%" valign="top">TDS 12个线程</td>
<td width="11%" valign="top">930</td>
<td width="8%" valign="top">24</td>
<td width="12%" valign="top">112,735</td>
<td width="9%" valign="top">518</td>
<td width="12%" valign="top">1,013</td>
<td width="8%" valign="top">20</td>
<td width="12%" valign="top">2,658</td>
<td width="9%" valign="top">149</td>
</tr>
<tr>
<td width="15%" valign="top">TDS 16个线程</td>
<td width="11%" valign="top">968</td>
<td width="8%" valign="top">13</td>
<td width="12%" valign="top">99,860</td>
<td width="9%" valign="top">820</td>
<td width="12%" valign="top">1,085</td>
<td width="8%" valign="top">34</td>
<td width="12%" valign="top">2,837</td>
<td width="9%" valign="top">117</td>
</tr>
</tbody>
</table>
<p><a href="http://www.bdbchina.com/wp-content/uploads/2011/09/perf_01.bmp"><img class="aligncenter size-full wp-image-1700" title="perf_01" src="http://www.bdbchina.com/wp-content/uploads/2011/09/perf_01.bmp" alt="" width="573" height="417" /></a></p>
<p>图1. 在SMP系统上，配置不同线程数对应的TDS性能</p>
<h1>SQL接口性能概述</h1>
<p>目前有很多流行的基准（benchmarks）是专门为基于SQL的关系数据库而设的。为适应Berkeley DB的SQL接口，我们参考实现了类似的基准。</p>
<p>我们的实验启发自两种流行基准: 事务处理性能委员会的TPC- B基准<sup>1</sup>和D. J. DeWitt 的Wisconsin基准<sup>2</sup>。</p>
<p>这些基准实现和测试数据, 没有被第三方验证或审核，而仅仅作为我们在不需要其它软件系统介入的情况下试图去认识有关BDB性能特征所做的努力。</p>
<h2>TPC-B 基准</h2>
<p>TPC-B基准的测试需要实现TPC B规范要求的一些模式（Schema）和标准事务。帐户（accounts）的数目是按比例下降的，这样做的目的是在运行的时候方便管理。它有1000家分支机构（branches），总共拥有10000个出纳员（tellers）和100,000个帐户。</p>
<p>下表显示的是由TPC B生成的事务吞吐率（以每秒的事务数（TPS）为单位）。这些结果是从一个256兆字节大小的数据库缓存中得到。</p>
<p>表6- TPC-B 事务吞吐率</p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top">线程数</td>
<td valign="top">事务吞吐率（TPS）</td>
</tr>
<tr>
<td valign="top">1</td>
<td valign="top">1846.71</td>
</tr>
<tr>
<td valign="top">2</td>
<td valign="top">2310.84</td>
</tr>
<tr>
<td valign="top">3</td>
<td valign="top">2508.26</td>
</tr>
<tr>
<td valign="top">4</td>
<td valign="top">2678.14</td>
</tr>
<tr>
<td valign="top">5</td>
<td valign="top">2808.51</td>
</tr>
<tr>
<td valign="top">10</td>
<td valign="top">2859.15</td>
</tr>
</tbody>
</table>
<p style="text-align: center;"><a href="http://www.bdbchina.com/wp-content/uploads/2011/09/perf_02.bmp"><img class="aligncenter size-full wp-image-1701" title="perf_02" src="http://www.bdbchina.com/wp-content/uploads/2011/09/perf_02.bmp" alt="" width="643" height="467" /></a></p>
<p>图2. 由类TPC-B基准衡量的每秒事务数（TPS）以及对应的线程数</p>
<h2>Wisconsin 基准</h2>
<p>本测试尝试按照Wisconsin 基准规范规定的模式和查询进行，但是并没有尝试去降低由数据库系统和操作系统引起的缓存效应。</p>
<p>这个实验衡量了在标准数据库上进行大量不同测试案例的单用户性能。所有的测试案例组合的结果可用于分析一个数据库的优势和弱势。对于查询的描述，请参阅链接<sup>4</sup>中的附录一。</p>
<p>为了这些实验能够正常运行，数据库是配置了针对单线程和单用户访问的编译优化选项。每个查询运行10次，下表显示的是平均需要的运行时间，以毫秒为单位。</p>
<p>表7. 由Wisconsin基准衡量的平均运行时间</p>
<table border="1" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td width="8%" valign="top">案例编号</td>
<td width="15%" valign="top">运行时间（毫秒）</td>
<td width="8%" valign="top">案例编号</td>
<td width="17%" valign="top">运行时间（毫秒）</td>
<td width="8%" valign="top">案例编号</td>
<td width="16%" valign="top">运行时间（毫秒）</td>
<td width="8%" valign="top">案例编号</td>
<td width="15%" valign="top">运行时间（毫秒）</td>
</tr>
<tr>
<td width="8%" valign="top">1</td>
<td width="15%" valign="top">8.175</td>
<td width="8%" valign="top">9</td>
<td width="17%" valign="top">31047.220</td>
<td width="8%" valign="top">17</td>
<td width="16%" valign="top">16.944</td>
<td width="8%" valign="top">25</td>
<td width="15%" valign="top">18.163</td>
</tr>
<tr>
<td width="8%" valign="top">2</td>
<td width="15%" valign="top">13.875</td>
<td width="8%" valign="top">10</td>
<td width="17%" valign="top">3160.824</td>
<td width="8%" valign="top">18</td>
<td width="16%" valign="top">58.801</td>
<td width="8%" valign="top">26</td>
<td width="15%" valign="top">0.907</td>
</tr>
<tr>
<td width="8%" valign="top">3</td>
<td width="15%" valign="top">0.879</td>
<td width="8%" valign="top">11</td>
<td width="17%" valign="top">5335.219</td>
<td width="8%" valign="top">19</td>
<td width="16%" valign="top">136.595</td>
<td width="8%" valign="top">27</td>
<td width="15%" valign="top">3.844</td>
</tr>
<tr>
<td width="8%" valign="top">4</td>
<td width="15%" valign="top">6.749</td>
<td width="8%" valign="top">12</td>
<td width="17%" valign="top">9.920</td>
<td width="8%" valign="top">20</td>
<td width="16%" valign="top">3.944</td>
<td width="8%" valign="top">28</td>
<td width="15%" valign="top">4.380</td>
</tr>
<tr>
<td width="8%" valign="top">5</td>
<td width="15%" valign="top">1.368</td>
<td width="8%" valign="top">13</td>
<td width="17%" valign="top">9.942</td>
<td width="8%" valign="top">21</td>
<td width="16%" valign="top">32.566</td>
<td width="8%" valign="top">29</td>
<td width="15%" valign="top">1.081</td>
</tr>
<tr>
<td width="8%" valign="top">6</td>
<td width="15%" valign="top">11.017</td>
<td width="8%" valign="top">14</td>
<td width="17%" valign="top">11.585</td>
<td width="8%" valign="top">22</td>
<td width="16%" valign="top">32.774</td>
<td width="8%" valign="top">30</td>
<td width="15%" valign="top">1.273</td>
</tr>
<tr>
<td width="8%" valign="top">7</td>
<td width="15%" valign="top">0.244</td>
<td width="8%" valign="top">15</td>
<td width="17%" valign="top">19.407</td>
<td width="8%" valign="top">23</td>
<td width="16%" valign="top">0.102</td>
<td width="8%" valign="top">31</td>
<td width="15%" valign="top">1.252</td>
</tr>
<tr>
<td width="8%" valign="top">8</td>
<td width="15%" valign="top">1.373</td>
<td width="8%" valign="top">16</td>
<td width="17%" valign="top">14.759</td>
<td width="8%" valign="top">24</td>
<td width="16%" valign="top">17.742</td>
<td width="8%" valign="top">32</td>
<td width="15%" valign="top">1.081</td>
</tr>
</tbody>
</table>
<h1>参考</h1>
<p>1 <a href="http://www.tpc.org/tpcb/default.asp">http://www.tpc.org/tpcb/default.asp</a></p>
<p>2 <a href="http://firebird.sourceforge.net/download/test/wisconsin_benchmark_chapter4.pdf">http://firebird.sourceforge.net/download/test/wisconsin_benchmark_chapter4.pdf</a></p>
<p>3 <a href="http://www.tpc.org/tpcb/spec/tpcb_current.pdf">http://www.tpc.org/tpcb/spec/tpcb_current.pdf</a></p>
<p>4 <a href="http://firebird.sourceforge.net/download/test/wisconsin_benchmark_chapter4.pdf">http://firebird.sourceforge.net/download/test/wisconsin_benchmark_chapter4.pdf</a></p>
<h1>结束语</h1>
<p>Berkeley DB 键/值接口无论在单线程还是在多线程的应用程序上都执行地非常好。同时，如果一个应用程序并不需要完全的持久性的话，它将能非常显著地提高其性能。</p>
<p>Berkeley DB在11gR2 5.0的版本中增加基于键/值接口的SQL API。你可以从这里下载Oracle Berkeley DB:  <a href="http://www.oracle.com/technology/software/products/berkeley-db/index.html">http://www.oracle.com/technology/software/products/berkeley-db/index.html</a></p>
<p>你也可以在Oracle Technology Network (OTN) 论坛上发表相关评价以及提交问题：</p>
<p><a href="http://forums.oracle.com/forums/forum.jspa?forumID=271">http://forums.oracle.com/forums/forum.jspa?forumID=271</a></p>
<p>有关销售或者产品支持的信息，请发送Email到：<a href="../../Documents%20and%20Settings/haomwang/%E6%A1%8C%E9%9D%A2/berkeleydb-info_us@oracle.com">berkeleydb-info_us@oracle.com</a></p>
<p>想了解有关最新产品发布信息，请发送Email到：<a href="../../Documents%20and%20Settings/haomwang/%E6%A1%8C%E9%9D%A2/bdb-join@oss.oracle.com">bdb-join@oss.oracle.com</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.bdbchina.com/2011/09/oracle-berkeley-database-11g-r2-%e6%80%a7%e8%83%bd%e6%a6%82%e8%bf%b0%e7%99%bd%e7%9a%ae%e4%b9%a6/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>深入浅出BDB的批量操作</title>
		<link>http://www.bdbchina.com/2011/07/%e6%b7%b1%e5%85%a5%e6%b5%85%e5%87%babdb%e7%9a%84%e6%89%b9%e9%87%8f%e6%93%8d%e4%bd%9c/</link>
		<comments>http://www.bdbchina.com/2011/07/%e6%b7%b1%e5%85%a5%e6%b5%85%e5%87%babdb%e7%9a%84%e6%89%b9%e9%87%8f%e6%93%8d%e4%bd%9c/#comments</comments>
		<pubDate>Tue, 12 Jul 2011 11:12:24 +0000</pubDate>
		<dc:creator>傅翠云</dc:creator>
				<category><![CDATA[Berkeley DB]]></category>
		<category><![CDATA[Emily Fu]]></category>
		<category><![CDATA[bdb bulk Emily 傅翠云]]></category>

		<guid isPermaLink="false">http://www.bdbchina.com/?p=1675</guid>
		<description><![CDATA[（一）引言 
在处理大量数据时，也许你曾经面对这样的需求：
1.  查询某个时间的所有记录或者一段时间的记录；
2.  查询开通了增值业务的所有客户；
3.  查询最热门的搜索关键字；
4.  删除在某日开户的所有客户信息；
5.  更新在某网点的名称，并更新所有客户数据等等。
在上述场景中，需要对大量数据做相同的操作。如果逐条记录处理，那么频繁函数调用会消耗掉大量的计算资源，并且该方案可能不是最优的。为了有效地提高上述场景的性能，Berkeley DB 5.1（下文简称BDB）开始提供面向C，Java和C#语言的批量操作API（具体包括批量查询，更新和删除），一次即可批量返回满足需要的数据记录。
备注：
1.  BDB 3.3及以上版本支持批量查询， 4.8及以上版本支持批量更新和删除；BDB 4.8以上版本支持Java API批量查询、删除和更新。BDB 4.8及以上支持C# API批量查询，5.1及以上版本支持批量删除和更新。
2.  使用批量操作，不需要特别的编译选项。
3.  BDB SQL目前尚不支持上述批量操作。
本文将以C API为例，简要地介绍批量查询、更新和删除的原理和使用方法，并提供一个批量查询的范例。对于Java和C#用户，使用方法与C API类似，在此就不详细介绍，请参考相关文档。
（二）概述
传统的BDB是非关系型（NoSQL）数据库，每一条记录分为键值（key）和数据项（value），所有非键值的属性都存放在数据项中。BDB SQL扩展了SQL解析，使用SQL语法管理BDB数据库，目前BDB SQL尚未支持批量操作。
BDB批量操作和逐条操作的最大不同是使用缓冲区来存取输入、输出数据集。当使用批量操作时，应用程序通过记录设置缓冲区，来存取批量操作的数据集。针对不同的操作类型，缓冲区可能仅存键值，或仅存数据项，或二者皆存。例如，若查询某键值的所有数据项，则需要使用一个缓冲区，返回一定数量的数据项。
根据缓冲区是否既存键值又存数据项，BDB的批量操作分为两种模式，DB_MULTIPLE模式和DB_MULTIPLE_KEY模式。在DB_MULTIPLE的模式下，任一缓冲区只存键值或数据项。如果需要操作批量键值及其数据项，则应用程序需要为键值和数据项分别提供各自的缓冲区，且两个缓冲区里的键值和数据项一一对应。在DB_MULTIPLE_KEY模式下，应用程序仅需要提供一个缓冲区，以操作于批量记录（包括其键值和数据项）。
由于应用程序需要根据具体场合设置合理的缓冲区大小，从而达到最好的性能。下文将根据不同的操作，具体阐述缓冲区的使用，以便开发者更清晰地使用和理解BDB批量操作。
（三）批量查询
批量查询可以用来查询一个键值对应的所有数据项或者连续键值对应的所有数据项，并将查询结果分批返回到缓冲区。例如，查询某帐户的所有交易记录，假设每条交易记录长度是100字节，设置一个1024字节大小的缓冲区，每次数据库可以读取满足条件的10条记录到该缓冲区；处理完该批记录后，BDB可继续提取下一批的10条记录，直到处理完所有满足条件的记录为止。
目前BDB批量查询仅支持查询连续的数据记录。若需要查询不连续的数据记录，可以在应用程序层面做一些处理，尽可能对连续的或者相邻的记录一块做查询。
批量查询通过调用以下接口实现:
-   DB-&#62;get(DB *db,DB_TXN *txnid, DBT *key, DBT *data, u_int32_t flags)
-   DBcursor-&#62;get(DBC *DBcursor, DBT *key, DBT *data, u_int32_t flags);
根据用户提供的键值或者游标所在位置，返回该键值对应的数据项，或者游标所在位置后一定数量的数据集。在调用的接口函数中，用于返回批量结果的DBT的data域指向应用程序提供的可用缓冲区，ulen域为缓冲区大小，flags域为DB_DBT_USERMEM。
在批量查询中,DB-&#62;get()支持DB_MULTIPLE模式，而DBC-&#62;get()可以同时支持DB_MULTIPLE和DB_MULTIPLE_KEY模式。
使用不同的模式和访问方法，得到的缓冲格式不尽相同。由于应用程序需要从缓冲中依次读出每一个数据项，因此，在此将更详尽地介绍一下各种缓冲格式和读取数据项的方法。
1.  DB_MULTIPLE模式下得到的只含批量数据项或者只含批量键值的缓冲：



Data1
Data2
…
DataN
-1
LengthN
OffsetN
…
Length2
Offset2
Length1
Offset1



Img 1 DB_MULTIPLE 缓冲
读取该缓冲中的每一个数据项的过程如下：
-       DB_MULTIPLE_INIT初始化读指针；
-       DB_MULTIPLE_NEXT依次读出每一个数据项。
2.  DB_MULTIPLE_KEY模式下得到的是一个含批量键值和数据项的缓冲：
1)   当数据库为BTree或者Hash时，



Key1
Data1
…
KeyN
DataN
-1
DLengthN
DOffsetN
KLengthN
KOffsetN
 






 
…
DLength2
DOffset2
KLength1
KOffset1



Img 2 DB_MULTIPLE_KEY 非recno 缓冲
读取该缓冲中的每一个键值和数据项的过程如下：
-       DB_MULTIPLE_INIT初始化读指针；
-       [...]]]></description>
			<content:encoded><![CDATA[<p><span style="color: #000000;"><strong>（一）引言 </strong></span></p>
<p><span style="color: #000000;">在处理大量数据时，也许你曾经面对这样的需求：</span></p>
<p><span style="color: #000000;">1.  查询某个时间的所有记录或者一段时间的记录；</span></p>
<p><span style="color: #000000;">2.  查询开通了增值业务的所有客户；</span></p>
<p><span style="color: #000000;">3.  查询最热门的搜索关键字；</span></p>
<p><span style="color: #000000;">4.  删除在某日开户的所有客户信息；</span></p>
<p><span style="color: #000000;">5.  更新在某网点的名称，并更新所有客户数据等等。</span></p>
<p><span style="color: #000000;">在上述场景中，需要对大量数据做相同的操作。如果逐条记录处理，那么频繁函数调用会消耗掉大量的计算资源，并且该方案可能不是最优的。为了有效地提高上述场景的性能，Berkeley DB 5.1（下文简称BDB）开始提供面向C，Java和C#语言的批量操作API（具体包括批量查询，更新和删除），一次即可批量返回满足需要的数据记录。<span id="more-1675"></span></span></p>
<p><span style="color: #000000;">备注：</span></p>
<p><span style="color: #000000;">1.  BDB 3.3及以上版本支持批量查询， 4.8及以上版本支持批量更新和删除；BDB 4.8以上版本支持Java API批量查询、删除和更新。BDB 4.8及以上支持C# API批量查询，5.1及以上版本支持批量删除和更新。</span></p>
<p><span style="color: #000000;">2.  使用批量操作，不需要特别的编译选项。</span></p>
<p><span style="color: #000000;">3.  BDB SQL目前尚不支持上述批量操作。</span></p>
<p><span style="color: #000000;">本文将以C API为例，简要地介绍批量查询、更新和删除的原理和使用方法，并提供一个批量查询的范例。对于Java和C#用户，使用方法与C API类似，在此就不详细介绍，请参考相关文档。</span></p>
<p><span style="color: #000000;"><strong>（二）概述</strong></span></p>
<p><span style="color: #000000;">传统的BDB是非关系型（NoSQL）数据库，每一条记录分为键值（key）和数据项（value），所有非键值的属性都存放在数据项中。BDB SQL扩展了SQL解析，使用SQL语法管理BDB数据库，目前BDB SQL尚未支持批量操作。</span></p>
<p><span style="color: #000000;">BDB批量操作和逐条操作的最大不同是使用缓冲区来存取输入、输出数据集。当使用批量操作时，应用程序通过记录设置缓冲区，来存取批量操作的数据集。针对不同的操作类型，缓冲区可能仅存键值，或仅存数据项，或二者皆存。例如，若查询某键值的所有数据项，则需要使用一个缓冲区，返回一定数量的数据项。</span></p>
<p><span style="color: #000000;">根据缓冲区是否既存键值又存数据项，BDB的批量操作分为两种模式，DB_MULTIPLE模式和DB_MULTIPLE_KEY模式。在DB_MULTIPLE的模式下，任一缓冲区只存键值或数据项。如果需要操作批量键值及其数据项，则应用程序需要为键值和数据项分别提供各自的缓冲区，且两个缓冲区里的键值和数据项一一对应。在DB_MULTIPLE_KEY模式下，应用程序仅需要提供一个缓冲区，以操作于批量记录（包括其键值和数据项）。</span></p>
<p><span style="color: #000000;">由于应用程序需要根据具体场合设置合理的缓冲区大小，从而达到最好的性能。下文将根据不同的操作，具体阐述缓冲区的使用，以便开发者更清晰地使用和理解BDB批量操作。</span></p>
<p><span style="color: #000000;"><strong>（三）批量查询</strong></span></p>
<p><span style="color: #000000;">批量查询可以用来查询一个键值对应的所有数据项或者连续键值对应的所有数据项，并将查询结果分批返回到缓冲区。例如，查询某帐户的所有交易记录，假设每条交易记录长度是100字节，设置一个1024字节大小的缓冲区，每次数据库可以读取满足条件的10条记录到该缓冲区；处理完该批记录后，BDB可继续提取下一批的10条记录，直到处理完所有满足条件的记录为止。</span></p>
<p><span style="color: #000000;">目前BDB批量查询仅支持查询连续的数据记录。若需要查询不连续的数据记录，可以在应用程序层面做一些处理，尽可能对连续的或者相邻的记录一块做查询。<br />
批量查询通过调用以下接口实现:<br />
-   DB-&gt;get(DB *db,DB_TXN *txnid, DBT *key, DBT *data, u_int32_t flags)<br />
-   DBcursor-&gt;get(DBC *DBcursor, DBT *key, DBT *data, u_int32_t flags);</span></p>
<p><span style="color: #000000;">根据用户提供的键值或者游标所在位置，返回该键值对应的数据项，或者游标所在位置后一定数量的数据集。在调用的接口函数中，用于返回批量结果的DBT的data域指向应用程序提供的可用缓冲区，ulen域为缓冲区大小，flags域为DB_DBT_USERMEM。<br />
在批量查询中,DB-&gt;get()支持DB_MULTIPLE模式，而DBC-&gt;get()可以同时支持DB_MULTIPLE和DB_MULTIPLE_KEY模式。</span></p>
<p><span style="color: #000000;">使用不同的模式和访问方法，得到的缓冲格式不尽相同。由于应用程序需要从缓冲中依次读出每一个数据项，因此，在此将更详尽地介绍一下各种缓冲格式和读取数据项的方法。</span></p>
<p><span style="color: #000000;">1.  DB_MULTIPLE模式下得到的只含批量数据项或者只含批量键值的缓冲：</span></p>
<table border="1" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td width="8%" valign="top"><span style="color: #000000;">Data1</span></td>
<td width="8%" valign="top"><span style="color: #000000;">Data2</span></td>
<td width="4%" valign="top"><span style="color: #000000;">…</span></td>
<td width="8%" valign="top"><span style="color: #000000;">DataN</span></td>
<td width="4%" valign="top"><span style="color: #000000;">-1</span></td>
<td width="10%" valign="top"><span style="color: #000000;">LengthN</span></td>
<td width="10%" valign="top"><span style="color: #000000;">OffsetN</span></td>
<td width="4%" valign="top"><span style="color: #000000;">…</span></td>
<td width="10%" valign="top"><span style="color: #000000;">Length2</span></td>
<td width="9%" valign="top"><span style="color: #000000;">Offset2</span></td>
<td width="10%" valign="top"><span style="color: #000000;">Length1</span></td>
<td width="9%" valign="top"><span style="color: #000000;">Offset1</span></td>
</tr>
</tbody>
</table>
<p style="text-align: center;"><span style="color: #000000;">Img 1 DB_MULTIPLE 缓冲</span></p>
<p><span style="color: #000000;">读取该缓冲中的每一个数据项的过程如下：<br />
-       DB_MULTIPLE_INIT初始化读指针；<br />
-       DB_MULTIPLE_NEXT依次读出每一个数据项。</span></p>
<p><span style="color: #000000;">2.  DB_MULTIPLE_KEY模式下得到的是一个含批量键值和数据项的缓冲：</span></p>
<p><span style="color: #000000;">1)   当数据库为BTree或者Hash时，</span></p>
<table border="1" cellspacing="0" cellpadding="0" width="94%">
<tbody>
<tr>
<td width="7%" valign="top"><span style="color: #000000;">Key1</span></td>
<td width="8%" valign="top"><span style="color: #000000;">Data1</span></td>
<td width="4%" valign="top"><span style="color: #000000;">…</span></td>
<td width="8%" valign="top"><span style="color: #000000;">KeyN</span></td>
<td width="9%" valign="top"><span style="color: #000000;">DataN</span></td>
<td width="4%" valign="top"><span style="color: #000000;">-1</span></td>
<td width="13%" valign="top"><span style="color: #000000;">DLengthN</span></td>
<td width="12%" valign="top"><span style="color: #000000;">DOffsetN</span></td>
<td width="12%" valign="top"><span style="color: #000000;">KLengthN</span></td>
<td width="11%" valign="top"><span style="color: #000000;">KOffsetN</span></td>
<td width="6%" valign="top"><span style="color: #000000;"> </span></td>
</tr>
</tbody>
</table>
<table border="1" cellspacing="0" cellpadding="0" width="57%">
<tbody>
<tr>
<td width="12%" valign="top"><span style="color: #000000;"> </span></td>
<td width="7%" valign="top"><span style="color: #000000;">…</span></td>
<td width="21%" valign="top"><span style="color: #000000;">DLength2</span></td>
<td width="19%" valign="top"><span style="color: #000000;">DOffset2</span></td>
<td width="20%" valign="top"><span style="color: #000000;">KLength1</span></td>
<td width="19%" valign="top"><span style="color: #000000;">KOffset1</span></td>
</tr>
</tbody>
</table>
<p style="text-align: center;"><span style="color: #000000;">Img 2 DB_MULTIPLE_KEY 非recno 缓冲</span></p>
<p><span style="color: #000000;">读取该缓冲中的每一个键值和数据项的过程如下：<br />
-       DB_MULTIPLE_INIT初始化读指针；<br />
-       DB_MULTIPLE_KEY_NEXT依次读出每一条记录，并获得其键值和数据项。</span></p>
<p><span style="color: #000000;">2)  当数据库为Recno或者Queue时候，</span></p>
<table border="1" cellspacing="0" cellpadding="0" width="574">
<tbody>
<tr>
<td width="48" valign="top"><span style="color: #000000;">Data1</span></td>
<td width="48" valign="top"><span style="color: #000000;">Data2</span></td>
<td width="24" valign="top"><span style="color: #000000;">…</span></td>
<td width="50" valign="top"><span style="color: #000000;">DataN</span></td>
<td width="22" valign="top"><span style="color: #000000;">0</span></td>
<td width="62" valign="top"><span style="color: #000000;">LengthN</span></td>
<td width="58" valign="top"><span style="color: #000000;">OffsetN</span></td>
<td width="58" valign="top"><span style="color: #000000;">RecnoN</span></td>
<td width="24" valign="top"><span style="color: #000000;">…</span></td>
<td width="58" valign="top"><span style="color: #000000;">Length1</span></td>
<td width="58" valign="top"><span style="color: #000000;">Offset1</span></td>
<td width="65" valign="top"><span style="color: #000000;">Recno1</span></td>
</tr>
</tbody>
</table>
<p style="text-align: center;"><span style="color: #000000;">Img 3 DB_MULTIPLE_KEY recno缓冲</span></p>
<p><span style="color: #000000;">读取该缓冲中的每一个键值和数据项的过程如下：<br />
-      DB_MULTIPLE_INIT初始化读指针；<br />
-      DB_MULTIPLE_RECNO_NEXT依次读出每一个记录，并获得其recno和数据项。</span></p>
<p><span style="color: #000000;">BDB批量查询的一个重要应用是：实现分页技术。当查询连续记录，若每条记录长度稳定，选择合适的缓冲大小，可使当前分页结果即是每次返回到缓冲的记录。若记录长度不一时，可计算当前分页的最后一个键值，并保留其后的记录，待下一次批量查询时，并到下一个分页中。当数据量较大，亦可将结果暂存在一个临时内存数据库中。</span></p>
<p><span style="color: #000000;">本文将在第六部分具体介绍一个批量查询的实例。</span></p>
<p><span style="color: #000000;"><strong>（四）批量更新</strong></span></p>
<p><span style="color: #000000;">批量更新将不同的键值和数据项一一写入给定缓冲区，并调用DB-&gt;put()写接口，批量写入或者更新这些数据记录。DB-&gt;put()支持DB_MULTIPLE和DB_MULTIPLE_KEY两种模式的批量更新。</span></p>
<p><span style="color: #000000;">1.  DB_MULTIPLE模式</span></p>
<p><span style="color: #000000;">DB-&gt;put()中的key和data分别指向两个不同的缓冲，前者存储批量键值，后者存储相同数量的批量数据项。缓冲的组装过程与访问控制相关。</span></p>
<p><span style="color: #000000;">1)  在BTree和Hash数据库中，缓冲组装过程如下：<br />
-       DB_MULTIPLE_WRITE_INIT分别初始化key和data的DBT；<br />
-       DB_MULTIPLE_WRITE_NEXT依次将每条记录的键值和数据项分别写入key和data。两个缓冲的格式与img 1相同。</span></p>
<p><span style="color: #000000;">2)  在Queue和Recno数据库中，缓冲组装过程如下<br />
-       DB_MULTIPLE_RECNO_WRITE_INIT分别初始化key和data的DBT；<br />
-       DB_MULTIPLE_RECNO_WRITE_NEXT依次将每条记录的recno和数据项分别写入key和data。存放数据项的缓冲的格式与img 1相同，存放键值的缓冲的格式如下所示：</span></p>
<table border="1" cellspacing="0" cellpadding="0" width="69%">
<tbody>
<tr>
<td width="5%" valign="top"><span style="color: #000000;">0</span></td>
<td width="15%" valign="top"><span style="color: #000000;">LengthN</span></td>
<td width="14%" valign="top"><span style="color: #000000;">OffsetN</span></td>
<td width="14%" valign="top"><span style="color: #000000;">RecnoN</span></td>
<td width="6%" valign="top"><span style="color: #000000;">…</span></td>
<td width="15%" valign="top"><span style="color: #000000;">Length1</span></td>
<td width="14%" valign="top"><span style="color: #000000;">Offset1</span></td>
<td width="14%" valign="top"><span style="color: #000000;">Recno1</span></td>
</tr>
</tbody>
</table>
<p style="text-align: center;"><span style="color: #000000;">Img 4 DB_MULTIPLE_KEY recno的键值缓冲</span></p>
<p><span style="color: #000000;">2.  DB_MULTIPLE_KEY模式</span></p>
<p><span style="color: #000000;">DB-&gt;put()中的key指向一个缓冲，该缓冲存储了成对的键值和数据项，而data为空。在BTree和Hash数据库中，缓冲的格式与Img 2相同。在Queue和Recno数据库中，缓冲的格式与Img 3相同。</span></p>
<p><span style="color: #000000;"><strong>（五）批量删除</strong></span></p>
<p><span style="color: #000000;">批量删除调用DB-&gt;del()接口，删除指定键值的所有记录，或者指定键值和数据项的所有记录。若删除二级索引中的记录，主数据库中的记录亦会被相应的删除。在逻辑上，成功的批量删除操作相当于循环地根据每一个键值或每一对键值/数据项删除其相应的记录。</span></p>
<p><span style="color: #000000;">DB-&gt;del()支持DB_MULTIPLE和DB_MULTIPLE_KEY两种模式。</span></p>
<p><span style="color: #000000;">1.  DB_MULTIPLE模式<br />
同批量更新中的DB_MULTIPLE模式类似，将一系列键值组装到key指定的缓冲中，并调用DB-&gt;del()，删除这些键值对应的一条或者多条记录。</span></p>
<p><span style="color: #000000;">2.  DB_MULTIPLE_KEY模式<br />
同批量更新中的DB_MULTIPLE_KEY模式类似，将一系列键值和其数据项组装到key指定的缓冲中，并调用DB-&gt;del()，删除这些键值和数据项所在的记录。</span></p>
<p><span style="color: #000000;"><strong>（六）运行示例程序</strong></span></p>
<p><span style="color: #000000;">在BDB发布包中的&lt;db-x.y.z&gt;/examples/c/ex_bulk.c演示了批量查询，更新和删除操作。这里将提供BTree数据库中批量查询的代码片段，并通过代码注释进行讲解。</span></p>
<p><span style="color: #000000;">本文将提供BTree数据库中批量查询的片段。</span></p>
<p><span style="color: #000000;"><code><br />
DBC *dbcp;<br />
DBT key, data;<br />
size_t retklen, retdlen;<br />
char *retkey, *retdata;<br />
int ret, t_ret;<br />
void *p;</code></span></p>
<p><span style="color: #000000;"><code>memset(&amp;key, 0, sizeof(key));<br />
memset(&amp;data, 0, sizeof(data));</code></span></p>
<p><span style="color: #000000;"><code>/* 分配5MB的缓冲空间 */<br />
#define    BUFFER_LENGTH    (5 * 1024 * 1024)<br />
if ((data.data = malloc(BUFFER_LENGTH)) == NULL)<br />
return (errno);<br />
data.ulen = BUFFER_LENGTH;<br />
data.flags = DB_DBT_USERMEM;</p>
<p>if ((ret = dbp-&gt;cursor(dbp, NULL, &amp;dbcp, 0)) != 0) {<br />
dbp-&gt;err(dbp, ret, "DB-&gt;cursor");<br />
free(data.data);<br />
return (ret);<br />
}</p>
<p>for (;;) {<br />
/* 游标遍历数据库，依次返回50MB的数据 */<br />
if ((ret = dbcp-&gt;c_get(dbcp,<br />
&amp;key, &amp;data, DB_MULTIPLE_KEY | DB_NEXT)) != 0) {<br />
if (ret != DB_NOTFOUND)<br />
dbp-&gt;err(dbp, ret, "DBcursor-&gt;c_get");<br />
break;<br />
}</p>
<p>/* 依次提取缓冲中每条数据 */<br />
for (DB_MULTIPLE_INIT(p, &amp;data);;) {<br />
DB_MULTIPLE_KEY_NEXT(p,<br />
&amp;data, retkey, retklen, retdata, retdlen);<br />
if (p == NULL)<br />
break;<br />
}<br />
}</p>
<p></code></span></p>
<p><span style="color: #000000;"><code>if ((t_ret = dbcp-&gt;c_close(dbcp)) != 0) {<br />
dbp-&gt;err(dbp, ret, "DBcursor-&gt;close");<br />
if (ret == 0)<br />
ret = t_ret;<br />
}<br />
free(data.data);<br />
</code></span></p>
<p><span style="color: #000000;"><strong>(七) 总结</strong></span></p>
<p><span style="color: #000000;">从上文可以看出，BDB通过引入缓冲区的技术实现了批量查询、批量更新和批量删除操作。事实证明，在大多数情况下可以获得明显的性能提升和减少磁盘IO的次数。当然，缓冲区大小的设置根据各个应用场合会不同，如何保证性能的同时兼顾缓冲区的大小是需要测试来获得的。<del datetime="2011-07-11T18:23" cite="mailto:Chao"></del></span></p>
<p><span style="color: #000000;">关于BDB的批量操作更详尽的信息，请参考文档：</span></p>
<ul>
<li><span style="color: #000000;"><a href="http://download.oracle.com/docs/cd/E17076_02/html/programmer_reference/am_misc_bulk.html"> http://download.oracle.com/docs/cd/E17076_02/html/programmer_reference/am_misc_bulk.html</a></span></li>
<li> <span style="color: #000000;"><a href="http://download.oracle.com/docs/cd/E17076_02/html/api_reference/C/dbt.html">http://download.oracle.com/docs/cd/E17076_02/html/api_reference/C/dbt.html</a></span></li>
</ul>
<p><span style="color: #000000;">关于BDB的更详尽的信息，请参考文档：</span></p>
<ul>
<li><span style="color: #000000;">BDB：http://download.oracle.com/docs/cd/E17076_02/html/</span></li>
<li><span style="color: #000000;">BDB中文博客：http://www.bdbchina.com/</span></li>
<li><span style="color: #000000;">BDB微博：http://weibo.com/bdbchina</span></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.bdbchina.com/2011/07/%e6%b7%b1%e5%85%a5%e6%b5%85%e5%87%babdb%e7%9a%84%e6%89%b9%e9%87%8f%e6%93%8d%e4%bd%9c/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Berkeley DB 5.2 ADO.NET开发包介绍</title>
		<link>http://www.bdbchina.com/2011/07/berkeley-db-5-2-ado-net%e5%bc%80%e5%8f%91%e5%8c%85%e4%bb%8b%e7%bb%8d/</link>
		<comments>http://www.bdbchina.com/2011/07/berkeley-db-5-2-ado-net%e5%bc%80%e5%8f%91%e5%8c%85%e4%bb%8b%e7%bb%8d/#comments</comments>
		<pubDate>Tue, 12 Jul 2011 06:19:03 +0000</pubDate>
		<dc:creator>赵汝聪</dc:creator>
				<category><![CDATA[Berkeley DB]]></category>
		<category><![CDATA[赵汝聪]]></category>
		<category><![CDATA[ADO.NET]]></category>
		<category><![CDATA[DBSQL]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://www.bdbchina.com/?p=1566</guid>
		<description><![CDATA[Berkeley DB 5.2版本在六月份顺利发布了。在这一版本中，我负责完成了Berkeley DB SQL (以下简称DBSQL)的第一个独立的ADO.NET发布包。以下向大家介绍一下其基本用法。
ADO.NET是微软在.NET Framework中负责数据访问的类库集，它是使用在COM时代奠基的OLE DB技术以及.NET Framework的类库和编程语言来发展的，它可以让.NET上的任何编程语言能够连接并访问关系数据库与非数据库型数据源（例如XML，Excel或是文字档数据），或是独立出来作为处理应用程序数据的类对象，其在.NET Framework中的地位是举足轻重，许多人将ADO.NET视为ADO的下一个版本，但其实它是一个全新的架构、产品与概念。
DBSQL ADO.NET包是一个针对Windows ADO.NET用户发布的独立包，已包含DBSQL所需的源代码和文件。ADO.NET用户可直接用它来编译生成基于Berkeley DB引擎的ADO.NET库。
用户可在Oracle Berkeley DB的官方网站下载以下文件：

Berkeley DB dbsql-adodotnet-5.2.28.zip, for ADO.NET (12M)

下文将详细介绍在Windows和Windows Mobile环境下的编译使用过程：

1. 环境需求
如果你的环境没有满足以下要求，相对应的工程是无法编译通过的：

System.Data.SQLite.Linq 需要 .Net Framework 3.5 SP1.
SQLite.Designer需要Microsoft Visual Studio SDK.

如果你不需要以上两个组件，可忽略相应的系统需求。
2. Windows
以Windows XP 32bit Visual Studio 2008为例:
打开SQLite.NET.2008.sln，如果遇到对话框询问加载方式，选择“正常加载项目”。
选择编译方式为ReleaseNative, Win32

编译整个项目。

测试生成的库：右键选择test.2008, 调试，启动新实例。点击“Run”，运行整个测试集。这些内置的ADO.NET测试同时也是很好的范例。

3. Windows Mobile
以下仍以Windows XP 32bit Visual Studio 2008为例。首先，要安装Windows Mobile 6.5.3 DTK (Developer Tool Kit) 在这里下载。
打开SQLite.NET.2008.WinCE.sln，如果遇到对话框询问加载方式，选择“正常加载项目”
然后，在”Mixed Platforms”所在的下拉菜单中选择“配置管理器”，然后如下图所示新建一个平台：

编译选项选择ReleaseNativeOnly, 然后编译整个工程。
编译通过后，将SQLite.Interop.2008.WinCE布署到Windows Mobile仿真器上：
右键选择SQLite.Interop.2008.WinCE, [...]]]></description>
			<content:encoded><![CDATA[<p>Berkeley DB 5.2版本在六月份顺利发布了。在这一版本中，我负责完成了Berkeley DB SQL (以下简称DBSQL)的第一个独立的ADO.NET发布包。以下向大家介绍一下其基本用法。</p>
<p>ADO.NET是微软在.NET Framework中负责数据访问的类库集，它是使用在COM时代奠基的OLE DB技术以及.NET Framework的类库和编程语言来发展的，它可以让.NET上的任何编程语言能够连接并访问关系数据库与非数据库型数据源（例如XML，Excel或是文字档数据），或是独立出来作为处理应用程序数据的类对象，其在.NET Framework中的地位是举足轻重，许多人将ADO.NET视为ADO的下一个版本，但其实它是一个全新的架构、产品与概念。</p>
<p>DBSQL ADO.NET包是一个针对Windows ADO.NET用户发布的独立包，已包含DBSQL所需的源代码和文件。ADO.NET用户可直接用它来编译生成基于Berkeley DB引擎的ADO.NET库。</p>
<p>用户可在Oracle Berkeley DB的官方网站<a href="http://www.oracle.com/technetwork/database/berkeleydb/downloads/index.html">下载</a>以下文件：</p>
<ul>
<li>Berkeley DB dbsql-adodotnet-5.2.28.zip, for ADO.NET (12M)</li>
</ul>
<p>下文将详细介绍在Windows和Windows Mobile环境下的编译使用过程：<br />
<span id="more-1566"></span></p>
<h2>1. 环境需求</h2>
<p>如果你的环境没有满足以下要求，相对应的工程是无法编译通过的：</p>
<ul>
<li>System.Data.SQLite.Linq 需要 .Net Framework 3.5 SP1.</li>
<li>SQLite.Designer需要Microsoft Visual Studio SDK.</li>
</ul>
<p>如果你不需要以上两个组件，可忽略相应的系统需求。</p>
<h2>2. Windows</h2>
<p>以Windows XP 32bit Visual Studio 2008为例:</p>
<p>打开SQLite.NET.2008.sln，如果遇到对话框询问加载方式，选择“正常加载项目”。</p>
<p>选择编译方式为ReleaseNative, Win32<br />
<a href="http://www.bdbchina.com/wp-content/uploads/2011/06/dbsql_adodotnet_1.png"><img class="alignnone size-full wp-image-1567" title="dbsql_adodotnet_1" src="http://www.bdbchina.com/wp-content/uploads/2011/06/dbsql_adodotnet_1.png" alt="" width="284" height="35" /></a></p>
<p>编译整个项目。<br />
<a href="http://www.bdbchina.com/wp-content/uploads/2011/06/dbsql_adodotnet_2.jpg"><img class="alignnone size-full wp-image-1568" title="dbsql_adodotnet_2" src="http://www.bdbchina.com/wp-content/uploads/2011/06/dbsql_adodotnet_2.jpg" alt="" width="500" height="415" /></a></p>
<p>测试生成的库：右键选择test.2008, 调试，启动新实例。点击“Run”，运行整个测试集。这些内置的ADO.NET测试同时也是很好的范例。<br />
<a href="http://www.bdbchina.com/wp-content/uploads/2011/06/dbsql_adodotnet_3.png"><img class="alignnone size-full wp-image-1569" title="dbsql_adodotnet_3" src="http://www.bdbchina.com/wp-content/uploads/2011/06/dbsql_adodotnet_3-300x258.png" alt="" width="400" height="344" /></a></p>
<h2>3. Windows Mobile</h2>
<p>以下仍以Windows XP 32bit Visual Studio 2008为例。首先，要安装Windows Mobile 6.5.3 DTK (Developer Tool Kit) 在<a href="http://www.microsoft.com/downloads/en/details.aspx?FamilyID=c0213f68-2e01-4e5c-a8b2-35e081dcf1ca&amp;displaylang=en">这里</a>下载。</p>
<p>打开SQLite.NET.2008.WinCE.sln，如果遇到对话框询问加载方式，选择“正常加载项目”</p>
<p>然后，在”Mixed Platforms”所在的下拉菜单中选择“配置管理器”，然后如下图所示新建一个平台：<br />
<a href="http://www.bdbchina.com/wp-content/uploads/2011/06/dbsql_adodotnet_4.png"><img class="alignnone size-full wp-image-1572" title="dbsql_adodotnet_4" src="http://www.bdbchina.com/wp-content/uploads/2011/06/dbsql_adodotnet_4.png" alt="" width="608" height="360" /></a></p>
<p><strong>编译选项选择ReleaseNativeOnly, 然后编译整个工程。</strong></p>
<p>编译通过后，将SQLite.Interop.2008.WinCE布署到Windows Mobile仿真器上：<br />
右键选择SQLite.Interop.2008.WinCE, 属性-&gt;部署-&gt;远程目录<br />
按需定义部署目录。这里为了方便演示下面的测试，将目录设定为：<br />
%CSIDL_PROGRAM_FILES%\testce</p>
<p>确定保存后，再次右键选择SQLite.Interop.2008.WinCE，选择部署。稍等一会后，当VisualStudio输出窗口显示以下内容，表明仿真器已经启动<br />
========== 部署: 成功1 个，失败0 个，跳过0 个==========<br />
<a href="http://www.bdbchina.com/wp-content/uploads/2011/06/dbsql_adodotnet_5.jpg"><img class="alignnone size-full wp-image-1573" title="dbsql_adodotnet_5" src="http://www.bdbchina.com/wp-content/uploads/2011/06/dbsql_adodotnet_5.jpg" alt="" width="262" height="406" /></a></p>
<p>同样的部署System.Data.SQLite.Compact.2008, 按下图所示选择仿真器<br />
<a href="http://www.bdbchina.com/wp-content/uploads/2011/06/dbsql_adodotnet_6.jpg"><img class="alignnone size-full wp-image-1574" title="dbsql_adodotnet_6" src="http://www.bdbchina.com/wp-content/uploads/2011/06/dbsql_adodotnet_6.jpg" alt="" width="367" height="222" /></a></p>
<p>右键选择testce.2008, 调试，启动新实例。如上图选择仿真器。测试集会自动运行，这些内置的ADO.NET测试同时也是很好的范例。运行结果如下所示(在仿真器中可用方向键对结果翻页)：<br />
<a href="http://www.bdbchina.com/wp-content/uploads/2011/06/dbsql_adodotnet_7.jpg"><img class="alignnone size-full wp-image-1575" title="dbsql_adodotnet_7" src="http://www.bdbchina.com/wp-content/uploads/2011/06/dbsql_adodotnet_7.jpg" alt="" width="262" height="406" /></a></p>
<h2>4. 结束语</h2>
<p>以上介绍了DBSQL ADO.NET发布包的编译使用过程。你可以在发布包的根目录下找到具体的官方文档。如果在使用过程中有任何问题，欢迎和我交流！</p>
<p>BDB Blog：<a href="http://www.bdbchina.com/">http://www.bdbchina.com/</a><br />
BDB微博：<a href="http://weibo.com/bdbchina">http://weibo.com/bdbchina</a><br />
个人微博：<a href="http://weibo.com/2153755234">http://weibo.com/2153755234</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.bdbchina.com/2011/07/berkeley-db-5-2-ado-net%e5%bc%80%e5%8f%91%e5%8c%85%e4%bb%8b%e7%bb%8d/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Berkeley DB 5.2 Android平台编译过程介绍</title>
		<link>http://www.bdbchina.com/2011/07/berkeley-db-5-2-android%e5%b9%b3%e5%8f%b0%e7%bc%96%e8%af%91%e8%bf%87%e7%a8%8b%e4%bb%8b%e7%bb%8d/</link>
		<comments>http://www.bdbchina.com/2011/07/berkeley-db-5-2-android%e5%b9%b3%e5%8f%b0%e7%bc%96%e8%af%91%e8%bf%87%e7%a8%8b%e4%bb%8b%e7%bb%8d/#comments</comments>
		<pubDate>Tue, 12 Jul 2011 06:19:00 +0000</pubDate>
		<dc:creator>赵汝聪</dc:creator>
				<category><![CDATA[Berkeley DB]]></category>
		<category><![CDATA[赵汝聪]]></category>
		<category><![CDATA[Android]]></category>
		<category><![CDATA[DBSQL]]></category>
		<category><![CDATA[Drop-in]]></category>

		<guid isPermaLink="false">http://www.bdbchina.com/?p=1584</guid>
		<description><![CDATA[在Berkeley DB 5.2版本中，Android Drop-in编译方式正式纳入官方发布文档。5.2的Android编译过程和先前我基于DBSQL 5.0写的博文稍有不同。以下介绍Oracle Berkeley DB 5.2官方文档中Android安装文档。欢迎交流。
Android默认提供的数据库功能是SQLite。Berkeley DBSQL完全兼容SQLite API，可以直接替换SQLite库而无需改动现有的应用程序或服务。依本方法编译得到的Berkeley DBSQL库将完全替换Android的SQLite库(drop-in模式)。在这种模式下，Android平台上所有的应用程序(包括我们自己编译的应用程序)都将链接到Berkeley DBSQL库以获取更高的存储和并发性能。
完整原文：http://download.oracle.com/docs/cd/E17076_02/html/installation/build_android_intro.html
中文介绍：

Android编译过程
本节提供了Berkeley DB Drop-in方式的Android编译指令。
首先要下载并且编译Android源代码树。
第一次编译过程需要花费较长一段时间，不过后面再编译就快多了。可以从这里下载Android的源代码并且按照Android文档完成编译过程。
把Berkeley DB代码目录拷到Android的代码目录里面：

$ cd ${root}/external/sqlite/dist
$ tar zxvf db-xx.tar.gz

这里的${root}指的是Android源代码树的根路径。
通过以下命令将源代码树中默认的Android.mk文件替换成Berkeley DB的版本：

$ cd ${root}/external/sqlite/dist
$ mv Android.mk Android.mk.sqlite
$ cp db-xx/build_android/Android.mk ./

提示：编译之前，可通过这里查看Android平台上的几种调优参数。
重新编译数据库部分，这样Berkeley DB就替换到最终生成的系统镜像了：

$ cd ${root}
$ . build/envsetup.sh
$ make clean-libsqlite
$ mmm -B external/sqlite/dist
$ make snod

以上指令完成后，新的基于Berkeley DB SQL的Android系统镜像即编译完毕。系统会打印出新的镜像所在目录，一般来说这个目录是：${root}/out/target/product/generic。 
从SQLite迁移到Berkeley DB
如果你需要使DBSQL能够自动打开并转换现有的SQLite数据库文件，请参照本节的步骤。
首先，我们需要通过以下脚本来为Android平台编译一个静态的SQLite shell, 这个shell对自动转换功能而言是必需的。

#!/bin/bash
# This script shows how to use built-in toolchain [...]]]></description>
			<content:encoded><![CDATA[<p>在Berkeley DB 5.2版本中，Android Drop-in编译方式正式纳入官方发布文档。5.2的Android编译过程和先前我基于DBSQL 5.0写的<a href="http://www.bdbchina.com/2010/04/%E5%9C%A8android%E5%B9%B3%E5%8F%B0%E4%B8%8A%E5%BA%94%E7%94%A8berkeley-db-11gr2-sqldrop-in%E6%A8%A1%E5%BC%8F/">博文</a>稍有不同。以下介绍Oracle Berkeley DB 5.2官方文档中Android安装文档。欢迎交流。</p>
<p>Android默认提供的数据库功能是SQLite。Berkeley DBSQL完全兼容SQLite API，可以直接替换SQLite库而无需改动现有的应用程序或服务。依本方法编译得到的Berkeley DBSQL库将完全替换Android的SQLite库(drop-in模式)。在这种模式下，Android平台上所有的应用程序(包括我们自己编译的应用程序)都将链接到Berkeley DBSQL库以获取<a href="http://www.bdbchina.com/2010/03/%E6%9B%B4%E5%A4%9A%E5%85%B3%E4%BA%8Eoracle-berkeley-db-sql%E7%9A%84%E6%8A%A5%E9%81%93/">更高的存储和并发性能</a>。</p>
<p>完整原文：http://download.oracle.com/docs/cd/E17076_02/html/installation/build_android_intro.html</p>
<p>中文介绍：<br />
<span id="more-1584"></span></p>
<h2>Android编译过程</h2>
<p>本节提供了Berkeley DB Drop-in方式的Android编译指令。</p>
<p>首先要下载并且编译Android源代码树。<br />
第一次编译过程需要花费较长一段时间，不过后面再编译就快多了。可以从<a href="http://source.android.com/source/download.html">这里</a>下载Android的源代码并且按照Android文档完成编译过程。</p>
<p>把Berkeley DB代码目录拷到Android的代码目录里面：</p>
<pre name="code" class="java:nogutter">
$ cd ${root}/external/sqlite/dist
$ tar zxvf db-xx.tar.gz
</pre>
<p>这里的${root}指的是Android源代码树的根路径。</p>
<p>通过以下命令将源代码树中默认的Android.mk文件替换成Berkeley DB的版本：</p>
<pre name="code" class="java:nogutter">
$ cd ${root}/external/sqlite/dist
$ mv Android.mk Android.mk.sqlite
$ cp db-xx/build_android/Android.mk ./
</pre>
<p>提示：编译之前，可通过<a href="http://download.oracle.com/docs/cd/E17076_02/html/installation/build_android_config.html">这里</a>查看Android平台上的几种调优参数。</p>
<p>重新编译数据库部分，这样Berkeley DB就替换到最终生成的系统镜像了：</p>
<pre name="code" class="java:nogutter">
$ cd ${root}
$ . build/envsetup.sh
$ make clean-libsqlite
$ mmm -B external/sqlite/dist
$ make snod
</pre>
<p>以上指令完成后，新的基于Berkeley DB SQL的Android系统镜像即编译完毕。系统会打印出新的镜像所在目录，一般来说这个目录是：${root}/out/target/product/generic。 </p>
<h2>从SQLite迁移到Berkeley DB</h2>
<p>如果你需要使DBSQL能够自动打开并转换现有的SQLite数据库文件，请参照本节的步骤。</p>
<p>首先，我们需要通过以下脚本来为Android平台编译一个静态的SQLite shell, 这个shell对自动转换功能而言是必需的。</p>
<pre name="code" class="java:nogutter">
#!/bin/bash
# This script shows how to use built-in toolchain to build
# sqlite3 shell, which is required by Berkeley DB SQL
# on-the-fly migration feature.

# Note: these variables should be set per active Android source tree
# We assume $PWD=$ROOT/external/sqlite/dist
ROOT=${PWD}/../../..
TOOLCHAIN=${ROOT}/prebuilt/linux-x86/toolchain/arm-eabi-4.4.0
CC=${TOOLCHAIN}/bin/arm-eabi-gcc
LIB="${ROOT}/out/target/product/generic/obj/lib"
INCLUDE="${ROOT}/ndk/build/platforms/android-8/arch-arm/usr/include"

# CFLAGS should be set per Android.mk.sqlite (the original
# version of SQLite's Android.mk)
CFLAGS="-DHAVE_USLEEP=1 -DSQLITE_THREADSAFE=1 -DNDEBUG=1 \
 -DSQLITE_DEFAULT_JOURNAL_SIZE_LIMIT=1048576 \
 -DSQLITE_ENABLE_MEMORY_MANAGEMENT=1 \
 -DSQLITE_DEFAULT_AUTOVACUUM=1 \
 -DSQLITE_TEMP_STORE=3 -DSQLITE_ENABLE_FTS3 \
 -DSQLITE_ENABLE_FTS3_BACKWARDS -DTHREADSAFE=1"
CFLAGS="${CFLAGS} -I${INCLUDE}"

LDFLAGS="-ldl -nostdlib -Wl,--gc-sections -lc -llog -lgcc \
 -Wl,--no-undefined,-z,nocopyreloc ${LIB}/crtend_android.o \
 ${LIB}/crtbegin_dynamic.o -L${LIB} -Wl,-rpath,${LIB}"

${CC} -DANDROID -DOS_ANDROID --sysroot="${SYSROOT}" -mandroid \
      -fvisibility=hidden -ffunction-sections -fdata-sections \
      -fPIC ${LDFLAGS} ${CFLAGS} \
      sqlite3.c shell.c -o sqlite3orig
</pre>
<p>提示：你可能需要根据当前环境来修改以上环境变量。</p>
<p>运行以上脚本，成功的话我们就得到了一个静态的sqlite3 shell工具 &#8211; sqlite3orig</p>
<p>接下来我们需要修改系统image文件。首先用xyaffs2工具解压镜像文件</p>
<pre name="code" class="java:nogutter">$ xyaffs2 ./system.img system</pre>
<p>把编译好的sqlite3工具拷进去。</p>
<pre name="code" class="java:nogutter">
$ cp ${root}/external/sqlite/dist/sqlite3orig system/xbin/sqlite3orig
</pre>
<p>使用mkyaffs2image工具来重新生成system.img.</p>
<pre name="code" class="java:nogutter">
$ mkyaffs2image -f $PWD/system system.img
</pre>
<p>这样，修改好的系统镜像即可自动转换并打开现成的SQLite3数据库文件。需要注意的是：在adb shell模式下，打开sqlite3数据库的命令是sqlite3orig；而打开Berkeley DBSQL数据库的命令是sqlite3。</p>
<h2>结束语</h2>
<p>以上介绍了DBSQL Android平台上Drop-in模式的编译使用过程。如果你在使用过程中有任何问题，欢迎和我交流！</p>
<p>BDB Blog：<a href="http://www.bdbchina.com">http://www.bdbchina.com</a><br />
BDB微博：<a href="http://weibo.com/bdbchina">http://weibo.com/bdbchina</a><br />
个人微博：<a href="http://weibo.com/2153755234">http://weibo.com/2153755234</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.bdbchina.com/2011/07/berkeley-db-5-2-android%e5%b9%b3%e5%8f%b0%e7%bc%96%e8%af%91%e8%bf%87%e7%a8%8b%e4%bb%8b%e7%bb%8d/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>一种新的BDB访问方法–Heap AM</title>
		<link>http://www.bdbchina.com/2011/07/heap-am-2/</link>
		<comments>http://www.bdbchina.com/2011/07/heap-am-2/#comments</comments>
		<pubDate>Mon, 04 Jul 2011 12:09:34 +0000</pubDate>
		<dc:creator>mingxingchen</dc:creator>
				<category><![CDATA[Berkeley DB]]></category>
		<category><![CDATA[Mingxing Chen]]></category>
		<category><![CDATA[AMs]]></category>
		<category><![CDATA[heap AM]]></category>

		<guid isPermaLink="false">http://www.bdbchina.com/?p=1613</guid>
		<description><![CDATA[在最新发布的Berkeley DB 5.2 版本中，我们引入了一种全新的数据库访问方法Heap Access Method (简称为Heap AM）。 加上之前BDB已支持的四种数据库访问方法：BTree、Hash、Queue和Recno，目前总共支持5种访问方法。本文仅对Heap AM做简单介绍, 有关其他访问方法的介绍请参照 – http://download.oracle.com/docs/cd/E17076_02/html/programmer_reference/am_conf.html 。
本文将从“使用Heap的目的”， “一个可能的应用场合”， “如何使用Heap AM”及它的“示例程序（ex_heap）介绍”几个方面展开阐述。

使用Heap AM的目的
在通常的OLTP应用中，频繁的插入和删除操作会带来很多额外的空间维护的开销。引入Heap AM的主要目的是，更好地重用磁盘空间，减少或者降低这部分开销。
当向Heap数据库增加一条新的记录时，它会从Heap数据库文件的起始页进行遍历以找到第一个有充足空间的页，并把这条记录写入该页中。这种插入方式使得Heap AM能够充分地利用数据库中每个页的空间，并能很好地控制数据库文件的过快增长。假设说，如果你的应用程序需要不断地对数据库进行等量插入和删除操作时（即，首先往数据库中插入一些记录，接着再删除相当数量的记录），Heap的数据库文件大小基本会保持一致。倘若，你使用其它AM, 例如BTree的话，由于BTree在插入一条记录时，是根据该记录的键值的排列顺序来决定该把记录放到哪个页中，所以BTree的数据库文件会比Heap的数据库文件在相同条件下增长得快些。
同时，你的应用程序还可以通过调用DB-&#62;set_heapsize()来显式地指定你的Heap数据库文件的物理大小。当达到指定大小后若继续增加记录，Heap 则会溢出并抛出DB_HEAP_FULL异常。
因此，相对其他的四种AM来说，Heap AM的一个很重要的优势是磁盘空间的复用。

一个可能的应用场合
Heap AM的加入主要源于行业中对于使用数据库做缓存的需求。通常来说，企业需要寻求一个方法能够使Berkeley DB运行在多台具有相同配置的机器上，并无须考虑BDB运行过程中磁盘空间的消耗情况。然而，如果仅仅是将Btree数据库中“老化”的记录（你可以理解为cache中不常访问的数据）驱除出去并不能立即释放可重用的空间，你还必须定期的进行数据库整理（compact）以释放空间。而整理操作通常都代价昂贵。Heap的访问方法避免了数据库整理的需要。它通常使用在一些运行在磁盘空间受限的应用程序中。

如何使用Heap AM
目前， Heap还不支API DB-&#62;set_partition()，因此一个heap数据库中的所有的记录仅仅被保存在一个Heap数据库文件中。每条记录通过其所在的位置进行访问。在一个Heap数据库中，键值是用来存储记录号（record id），其结构为&#60;页号：索引&#62;，即由该记录对应的数据值（data）所在页的页号（page）和其在页中的索引（index）2部分组成，并在第一次插入时被确定。
具体来讲，使用Heap访问方法仅仅涉及到以下几个步骤。
1)  在DB-&#62;open中使用DB_HEAP标志，以说明你的数据库将使用Heap访问方法。由于记录号具有唯一性，因此Heap数据库不支持DB_DUP或DB_DUPSORT。
if ((ret =
    dbp-&#62;open(dbp, NULL, dbname, NULL, DB_HEAP, DB_CREATE, 0)) != 0){
        dbenv-&#62;err(dbenv, ret, "DB-&#62;open");
 [...]]]></description>
			<content:encoded><![CDATA[<p>在最新发布的Berkeley DB 5.2 版本中，我们引入了一种全新的数据库访问方法Heap Access Method (简称为Heap AM）。 加上之前BDB已支持的四种数据库访问方法：BTree、Hash、Queue和Recno，目前总共支持5种访问方法。本文仅对Heap AM做简单介绍, 有关其他访问方法的介绍请参照 – <a href="http://download.oracle.com/docs/cd/E17076_02/html/programmer_reference/am_conf.html ">http://download.oracle.com/docs/cd/E17076_02/html/programmer_reference/am_conf.html </a>。</p>
<p>本文将从“使用Heap的目的”， “一个可能的应用场合”， “如何使用Heap AM”及它的“示例程序（ex_heap）介绍”几个方面展开阐述。</p>
<p><span id="more-1613"></span></p>
<h2>使用Heap AM的目的</h2>
<p>在通常的OLTP应用中，频繁的插入和删除操作会带来很多额外的空间维护的开销。引入Heap AM的主要目的是，更好地重用磁盘空间，减少或者降低这部分开销。</p>
<p>当向Heap数据库增加一条新的记录时，它会从Heap数据库文件的起始页进行遍历以找到第一个有充足空间的页，并把这条记录写入该页中。这种插入方式使得Heap AM能够充分地利用数据库中每个页的空间，并能很好地控制数据库文件的过快增长。假设说，如果你的应用程序需要不断地对数据库进行等量插入和删除操作时（即，首先往数据库中插入一些记录，接着再删除相当数量的记录），Heap的数据库文件大小基本会保持一致。倘若，你使用其它AM, 例如BTree的话，由于BTree在插入一条记录时，是根据该记录的键值的排列顺序来决定该把记录放到哪个页中，所以BTree的数据库文件会比Heap的数据库文件在相同条件下增长得快些。</p>
<p>同时，你的应用程序还可以通过调用DB-&gt;set_heapsize()来显式地指定你的Heap数据库文件的物理大小。当达到指定大小后若继续增加记录，Heap 则会溢出并抛出DB_HEAP_FULL异常。</p>
<p>因此，相对其他的四种AM来说，Heap AM的一个很重要的优势是磁盘空间的复用。</p>
<p><!--more--></p>
<h2>一个可能的应用场合</h2>
<p>Heap AM的加入主要源于行业中对于使用数据库做缓存的需求。通常来说，企业需要寻求一个方法能够使Berkeley DB运行在多台具有相同配置的机器上，并无须考虑BDB运行过程中磁盘空间的消耗情况。然而，如果仅仅是将Btree数据库中“老化”的记录（你可以理解为cache中不常访问的数据）驱除出去并不能立即释放可重用的空间，你还必须定期的进行数据库整理（compact）以释放空间。而整理操作通常都代价昂贵。Heap的访问方法避免了数据库整理的需要。它通常使用在一些运行在磁盘空间受限的应用程序中。</p>
<p><!--more--></p>
<h2>如何使用Heap AM</h2>
<p>目前， Heap还不支API DB-&gt;set_partition()，因此一个heap数据库中的所有的记录仅仅被保存在一个Heap数据库文件中。每条记录通过其所在的位置进行访问。在一个Heap数据库中，键值是用来存储记录号（record id），其结构为&lt;页号：索引&gt;，即由该记录对应的数据值（data）所在页的页号（page）和其在页中的索引（index）2部分组成，并在第一次插入时被确定。</p>
<p>具体来讲，使用Heap访问方法仅仅涉及到以下几个步骤。<br />
1)  在DB-&gt;open中使用DB_HEAP标志，以说明你的数据库将使用Heap访问方法。由于记录号具有唯一性，因此Heap数据库不支持DB_DUP或DB_DUPSORT。</p>
<pre class="java:nogutter">if ((ret =
    dbp-&gt;open(dbp, NULL, dbname, NULL, DB_HEAP, DB_CREATE, 0)) != 0){
        dbenv-&gt;err(dbenv, ret, "DB-&gt;open");
        return (ret);
}</pre>
<p>2) 当插入新的记录时，使用DB-&gt;put(&#8230;, DBT *key, DBT *data, &#8230;); 并需要指定标志DB_APPEND。此时，</p>
<p style="padding-left: 30px;">key（键值）是一个空的记录号&lt;页号：索引&gt;，它将在该记录插入完成后被自动赋值。<br />
data（数据值），也就是你的应用存储将要存储的那条记录。</p>
<pre class="java:nogutter">DB_HEAP_RID rid;
DBT key, data;
char buf[BUFFER_LEN];
int cnt, ret;

memset(&amp;rid, 0, sizeof(DB_HEAP_RID));
memset(&amp;key, 0, sizeof(DBT));
memset(&amp;data, 0, sizeof(DBT));

ret = 0;

key.data = &amp;rid;
key.size = key.ulen = sizeof(DB_HEAP_RID);
key.flags = DB_DBT_USERMEM;
data.data = buf;
data.flags = DB_DBT_USERMEM;

for (cnt = start; cnt &lt; (numrecs + start) &amp;&amp; (ret =
    generate_data(buf, cnt, test_var)) == 0; ++cnt) {
        data.size = data.ulen = (u_int32_t)strlen(buf) + 1;
        /* Require DB_APPEND flag to add new data to the database.*/
        if ((ret =  dbp-&gt;put(dbp, NULL, &amp;key, &amp;data, DB_APPEND)) != 0) {
            dbenv-&gt;err(dbenv, ret, "insert_heap:DB-&gt;put");
	    break;
        }
}</pre>
<p>3) 使用DB-&gt;set_heapsize(DB *dbp, u_int32_t gbytes, u_int32_t bytes); 来显式指定数据库文件的物理大小。此时，将创建一个大小为gbytes千兆+ bytes字节的Heap AM数据库文件。</p>
<pre class="java:nogutter">if ((ret = dbp-&gt;set_heapsize(dbp, ghpsize, hpsize, 0)) != 0) {
	dbenv-&gt;err(dbenv, ret, "DB-&gt;set_heapsize");
	return (ret);
}</pre>
<p><!--more--></p>
<h2>示例程序（ex_heap）介绍</h2>
<p>在新发布的Berkeley DB 5.2 中，由我负责添加了一个关于Heap AM的例子，名为ex_heap。你可以在&lt;db-5.2-XX&gt;/examples/c目录下找到ex_heap.c的文件，那个就是了。</p>
<p>ex_heap不仅演示了如何在BDB中使用Heap AM创建数据库，还比较Heap AM和BTree在存储数据方面的性能不同，例如在插入或删除过程中对应的数据库文件大小以及时间的变化。</p>
<p>ex_heap首先创建一个使用Heap作为访问方法的数据库，并初始化一定数量的记录。接下来进行至少2个轮回的插入和删除操作，即在每个轮回中，先插入一定数量的记录，接着删除相等数目的记录，同时记录每轮操作需要的时间及数据库文件大小的变化。</p>
<p>有兴趣用户可以从BDB下载页面下载最新的BDB5.2版本来体验下ex_heap, 解压后就可以使用了（为方便引用，记${BDB_HOME}为Berkeley DB源代码的根目录）。下面分别简要介绍下在Windows和Linux平台下如何编译ex_heap。</p>
<ul>
<li>Windows平台下编译ex_heap：</li>
</ul>
<p>在Windows下，编译ex_heap比较简单，只须用Visual Studio 2005/2008打开<br />
${BDB_HOME}/build_windows/Berkeley_DB.sln（或者使用Visual Studio 2010打开${BDB_HOME}/build_windows/Berkeley_DB_vs2010.sln），找到ex_heap的项目直接编译即可。如下图所示：</p>
<p><a href="http://www.bdbchina.com/wp-content/uploads/2011/07/windows_ex_heap.png"><img class="alignnone size-large wp-image-1649" title="windows_ex_heap" src="http://www.bdbchina.com/wp-content/uploads/2011/07/windows_ex_heap-1024x592.png" alt="" width="1024" height="592" /></a></p>
<ul>
<li>Linux平台下编译ex_heap：</li>
</ul>
<p>首先需要编译出BDB 5.2的库，然后再编译ex_heap, 具体步骤如下所示：</p>
<pre class="java:nogutter">$ cd ${BDB_HOME}/build_unix
$ ../dist/configure
$ make
$ make ex_heap</pre>
<p>使用ex_heap时，要求指定数据库环境所在的目录，同时ex_heap也提供很多额外的配置功能，比如，允许和BTree进行比较、允许指定cache的大小、使用定长还是变长数据做为输入、指定Heap AM数据库大小等等。可以用如下命令得到所有可配置信息：</p>
<pre class="java:nogutter">${BDB_HOME}/build_unix$ ./ex_heap</pre>
<p>具体可配置信息：</p>
<pre class="java:nogutter">usage: ex_heap:
[-b][-c cachesize][-d] -h home [-n recs_per_rep]
[-p pgsize][-r repeats][-S ghpsize][-s hpsize]
-b: run sample application using a btree database.
-c: specify the cache size for the environment.
-d: test on variable-length data (default: fix-length).
-h: specify the home directory for the environment (required).
-n: specify the num. of records per repetition (default: 10000).
-p: specify the pgsize of database.
-r: number of repetition (a pair of insertion and deletion (default: 1).
-S: specify the heap size (gbytes) for the heap database.
-s: specify the heap size (bytes) for the heap database.</pre>
<p>比如我们使用以下命令来运行ex_heap：</p>
<pre class="java:nogutter">${BDB_HOME}/build_unix$./ex_heap -h exHeap -b -d -n 100000 -p 4096 -r 10 -s 4000000</pre>
<p>该命令中“-h exHeap”指定exHeap为环境目录，标志“-b”允许Heap AM和BTree在数据库文件增长方面和插入删除操作上性能的比较（不指定“-b”的话， 只考虑Heap AM在以上2方面的情况），标志“-d”表明在程序中使用可变长的记录进行插入删除操作（默认为固定长度的记录）， 标志“-n 100000”表明在每一个插入或删除操作中使用100000个记录，标志“-p 4096”指定数据库中的页大小为4096字节，标志“-r 10”指定在此次应用程序运行过程中进行10个轮回的插入删除操作，标志“-s 4000000”指定Heap数据库文件大小为4000000字节。</p>
<p>运行程序之后，输出的内容为：</p>
<pre class="java:nogutter">======================================================
About to enter the insert phase.
Database type: Heap     with configured heapsize = 0 gbytes and 4000000          bytes.
Pagesize: 4096
Initial records number: 10000
Number of repetitions: 10
Number of inserts per repetition: 100000

------------------------------------------------------
repetition       physical file size      running time
0                356352              0.01 seconds
1               3796992              0.30 seconds
2               4001792              0.29 seconds
3               4001792              0.29 seconds
4               4001792              0.29 seconds
5               4001792              0.29 seconds
6               4001792              0.30 seconds
7               4001792              0.29 seconds
8               4001792              0.29 seconds
9               4001792              0.29 seconds
10               4001792              0.30 seconds

======================================================
About to enter the insert phase.
Database type: Btree
Pagesize: 4096
Initial records number: 10000
Number of repetitions: 10
Number of inserts per repetition: 100000

------------------------------------------------------
repetition       physical file size      running time
0                458752              0.02 seconds
1               4984832              0.49 seconds
2               4993024              0.49 seconds
3               4988928              0.49 seconds
4               4993024              0.49 seconds
5               4988928              0.49 seconds
6               4988928              0.49 seconds
7               4993024              0.48 seconds
8               4988928              0.48 seconds
9               4984832              0.49 seconds
10               4984832              0.49 seconds</pre>
<p>从输出结果的对比可以看出，在相同的配置下，Heap AM不仅在时间开销上比BTree更有优势，而且只占用更小的数据库空间（文件大小）。</p>
<p><!--more--></p>
<h2>结束语</h2>
<p>如果您有任何问题，欢迎给我们的<a href="www.bdbchina.com">博客</a>或者<a href="http://weibo.com/bdbchina">BerkeleyDB的新浪微博</a>留言，也欢迎通过OTN论坛提问。</p>
<p style="padding-left: 30px;">BDB中文博客：<a href="www.bdbchina.com">www.bdbchina.com</a><br />
Oracle BDB 官方论坛：<a href="http://forums.oracle.com/forums/category.jspa?categoryID=246">http://forums.oracle.com/forums/category.jspa?categoryID=246</a><br />
BDB新浪微博：<a href="http://weibo.com/bdbchina">http://weibo.com/bdbchina</a><br />
个人新浪微博：<a href="http://weibo.com/redsuncmx">http://weibo.com/redsuncmx</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.bdbchina.com/2011/07/heap-am-2/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Berkeley DB SQL 5.2新Vacuum功能简介</title>
		<link>http://www.bdbchina.com/2011/07/berkeley-db-sql-5-2%e6%96%b0vacuum%e5%8a%9f%e8%83%bd%e7%ae%80%e4%bb%8b/</link>
		<comments>http://www.bdbchina.com/2011/07/berkeley-db-sql-5-2%e6%96%b0vacuum%e5%8a%9f%e8%83%bd%e7%ae%80%e4%bb%8b/#comments</comments>
		<pubDate>Fri, 01 Jul 2011 02:06:51 +0000</pubDate>
		<dc:creator>赵汝聪</dc:creator>
				<category><![CDATA[Berkeley DB]]></category>
		<category><![CDATA[赵汝聪]]></category>
		<category><![CDATA[DBSQL]]></category>
		<category><![CDATA[Vacuum]]></category>

		<guid isPermaLink="false">http://www.bdbchina.com/?p=1552</guid>
		<description><![CDATA[Berkeley DB 5.2版本在六月份顺利发布了。在这一版本中，我负责设计实现了Berkeley DB SQL的新Vacuum功能：增量Vacuum和Fill Percent参数。以下向大家介绍一下这些Vacuum功能的用法。
1. 什么是Vacuum
一个数据库在进行多次写操作(增,删,改)后，就会攒下一些碎片，即填充率非常低的页面(page)或是空白页面。这些页面占用了不少空间，却仅存储了少量数据。Vacuum的作用好比Windows下的磁盘碎片整理，即依次扫描数据库的数据页面，将数据搬移得更加紧凑，腾出空白页并且删除之，缩减数据库大小。Berkeley DB SQL(以下简称DBSQL)支持在线Vacuum(对一个正在运行的数据库进行操作)。你可以把它想像成扫描重排页面数据的写进程，这个进程可以和其它的所有OLDP操作并行执行。
在使用Vacuum时需要清楚以下要点：
- 整理数据碎片，回收文件系统空间，提升查询性能。
- 频繁操作会影响当前主业务性能。因此在DBSQL 5.2版本中，针对这一问题实现了增量Vacuum。用户可手动控制Vacuum操作涉及的数据块大小。
- 如果数据库被压得过紧，空闲空间不足，那么插入新数据时数据库需要频繁分配新页面，影响了操作性能。因此在DBSQL 5.2版本中，针对这一问题引入了Fill Percent参数。用户可手动控制Vacuum时的页面填充率。
以下具体介绍Berkeley DB SQL (以下简称DBSQL) 5.2版本中Vacuum功能的使用方法：

2. 使用Vacuum功能
2.1 基本Vacuum命令
基本的Vacuum命令是对全数据库进行Vacuum。直接在SQL语句或者SHELL里面执行&#8221;VACUUM&#8221;指令，即完成一次基本Vacuum：

VACUUM;

当数据库较大时，一次Vacuum将会耗费较多的时间，影响数据库的正常业务响应时间。此外，全数据库Vacuum是放在一个事务里面完成的，在资源受限的情况下，有可能无法一次完成对整个数据库的操作。
2.2 增量Vacuum
BDB 5.2实现了增量Vacuum。所谓增量，即每次Vacuum仅操作一小部分数据块，下一次再从上次结束的地方继续操作，如此反复进行，就可以完成整个数据库的Vacuum，同时也不会对主业务有明显影响。比如说 在一天中操作频率较低的时间段(夜间)，可以启动一个并行的维护程序，在数据库业务正常运行的同时，周期性地调用增量Vaccum来回收空间。
要使用增量Vacuum，需要先设定每次操作回收的最大页数(默认值为128页)。命令为：

PRAGMA bdbsql_vacuum_pages [=N]

此参数用于获得或者设定一次增量Vacuum操作的最大回收页数。当回收的页数大于该值时候，当前增量Vacuum完成并退出。如果未设定N，返回当前的最大回收页数。
设定了该参数后，我们有两种方式来使用增量Vacuum:

1. 手动
这种方式可以自由地控制Vacuum的频率和时机，也是推荐的方法。使用办法：首先调用&#8221;PRAGMA auto_vacuum=INCREMENTAL&#8221;来置为手动增量Vacuum模式，然后在程序中即可调用&#8221;PRAGMA incremental_vacuum(N)&#8221;来执行一次增量vacuum。
2. 自动
在自动模式下，DBSQL在提交事务后会自动执行一次增量Vacuum。这种方式的好处是不需要额外的程序控制，但如果事务提交非常频繁，会带来额外的负担。使用办法：调用&#8221;PRAGMA auto_vacuum=FULL&#8221;来设置数据库为自动增量Vacuum模式。

在数据库运行过程中，可用以上指令在手动和自动模式间切换。
2.3 Fill Percent
在DBSQL 5.2中我们引入了一个新的Vacuum参数：页面填充率。用法:

PRAGMA bdbsql_vacuum_fillpercent [=N]

此参数用于获得或者设置预期的数据库页面填充率。所有DBSQL Vacuum模式均受此参数控制。N为填充率百分比(1~100)，当N被设定时，DBSQL Vacuum会以N为目标重排数据库页。当N未被设定时，返回当前设定的页填充率(默认值为85).
Vacuum操作包括两方面：

1. 数据页重排
只有当页填充率百分比低于N时，DBSQL才会重排该页，将其它页面的数据挪到未使用的空间，使其填充率尽可能地接近目标值。被搬空的页面就成了新的空白页。
2. 空白页回收
统一将空白页挪到文件末端，删除空白页并截短数据库文件。


Fill Percent参数的引入，丰富了用户Vacuum操作的手段。在不同情况下用户可以选择不同的Fill Percent参数来精细化操作。典型的应用:

对于一个正在工作的数据库，用一个非常低的Fill Percent值(比如1)来快速回收数据库中已存在的空页。因为这种情况下不存在页内数据搬移，数据库仅仅将现有的空页交换到尾部并截短，不会对现有数据加锁，速度会非常快。
对于一个处于关闭状态的数据库，用一个较高的Fill Percent值来尽可能地回收空间。

这里有一个问题：假设用户设定目标Fill Percent值为80(%)，每条数据约占15%的空间。那么重排后该页应该存储5条数据(75%，更接近于目标值)还是6条数据(90%，更大填充率)呢。这是一个设计上的权衡选择。关于这一点，我们经过内部讨论后选择了前者。即令填充率接近于目标值，而不是尽可能地大。&#8221;Some applications want room to add data on the page, others [...]]]></description>
			<content:encoded><![CDATA[<p>Berkeley DB 5.2版本在六月份顺利发布了。在这一版本中，我负责设计实现了Berkeley DB SQL的新Vacuum功能：增量Vacuum和Fill Percent参数。以下向大家介绍一下这些Vacuum功能的用法。</p>
<h2>1. 什么是Vacuum</h2>
<p>一个数据库在进行多次写操作(增,删,改)后，就会攒下一些碎片，即填充率非常低的页面(page)或是空白页面。这些页面占用了不少空间，却仅存储了少量数据。Vacuum的作用好比Windows下的磁盘碎片整理，即依次扫描数据库的数据页面，将数据搬移得更加紧凑，腾出空白页并且删除之，缩减数据库大小。Berkeley DB SQL(以下简称DBSQL)支持在线Vacuum(对一个正在运行的数据库进行操作)。你可以把它想像成扫描重排页面数据的写进程，这个进程可以和其它的所有OLDP操作并行执行。</p>
<p><strong>在使用Vacuum时需要清楚以下要点：</strong><br />
- 整理数据碎片，回收文件系统空间，提升查询性能。<br />
- 频繁操作会影响当前主业务性能。因此在DBSQL 5.2版本中，针对这一问题实现了增量Vacuum。用户可手动控制Vacuum操作涉及的数据块大小。<br />
- 如果数据库被压得过紧，空闲空间不足，那么插入新数据时数据库需要频繁分配新页面，影响了操作性能。因此在DBSQL 5.2版本中，针对这一问题引入了Fill Percent参数。用户可手动控制Vacuum时的页面填充率。</p>
<p>以下具体介绍Berkeley DB SQL (以下简称DBSQL) 5.2版本中Vacuum功能的使用方法：<br />
<span id="more-1552"></span></p>
<h2>2. 使用Vacuum功能</h2>
<p><strong>2.1 基本Vacuum命令</strong><br />
基本的Vacuum命令是对全数据库进行Vacuum。直接在SQL语句或者SHELL里面执行&#8221;VACUUM&#8221;指令，即完成一次基本Vacuum：</p>
<ul>
<li><code>VACUUM;</code></li>
</ul>
<p>当数据库较大时，一次Vacuum将会耗费较多的时间，影响数据库的正常业务响应时间。此外，全数据库Vacuum是放在一个事务里面完成的，在资源受限的情况下，有可能无法一次完成对整个数据库的操作。</p>
<p><strong>2.2 增量Vacuum</strong><br />
BDB 5.2实现了增量Vacuum。所谓增量，即每次Vacuum仅操作一小部分数据块，下一次再从上次结束的地方继续操作，如此反复进行，就可以完成整个数据库的Vacuum，同时也不会对主业务有明显影响。比如说 在一天中操作频率较低的时间段(夜间)，可以启动一个并行的维护程序，在数据库业务正常运行的同时，周期性地调用增量Vaccum来回收空间。</p>
<p>要使用增量Vacuum，需要先设定每次操作回收的最大页数(默认值为128页)。命令为：</p>
<ul>
<li><code>PRAGMA bdbsql_vacuum_pages [=N]</code></li>
</ul>
<p>此参数用于获得或者设定一次增量Vacuum操作的最大回收页数。当回收的页数大于该值时候，当前增量Vacuum完成并退出。如果未设定N，返回当前的最大回收页数。</p>
<p>设定了该参数后，我们有两种方式来使用增量Vacuum:</p>
<ul>
<li><strong>1. 手动</strong><br />
这种方式可以自由地控制Vacuum的频率和时机，也是推荐的方法。使用办法：首先调用&#8221;PRAGMA auto_vacuum=INCREMENTAL&#8221;来置为手动增量Vacuum模式，然后在程序中即可调用&#8221;PRAGMA incremental_vacuum(N)&#8221;来执行一次增量vacuum。</li>
<li><strong>2. 自动</strong><br />
在自动模式下，DBSQL在提交事务后会自动执行一次增量Vacuum。这种方式的好处是不需要额外的程序控制，但如果事务提交非常频繁，会带来额外的负担。使用办法：调用&#8221;PRAGMA auto_vacuum=FULL&#8221;来设置数据库为自动增量Vacuum模式。</li>
</ul>
<p>在数据库运行过程中，可用以上指令在手动和自动模式间切换。</p>
<p><strong>2.3 Fill Percent</strong><br />
在DBSQL 5.2中我们引入了一个新的Vacuum参数：页面填充率。用法:</p>
<ul>
<li>PRAGMA bdbsql_vacuum_fillpercent [=N]</li>
</ul>
<p>此参数用于获得或者设置预期的数据库页面填充率。所有DBSQL Vacuum模式均受此参数控制。N为填充率百分比(1~100)，当N被设定时，DBSQL Vacuum会以N为目标重排数据库页。当N未被设定时，返回当前设定的页填充率(默认值为85).</p>
<p>Vacuum操作包括两方面：</p>
<ul>
<li><strong>1. 数据页重排</strong><br />
只有当页填充率百分比低于N时，DBSQL才会重排该页，将其它页面的数据挪到未使用的空间，使其填充率尽可能地接近目标值。被搬空的页面就成了新的空白页。</li>
<li><strong>2. 空白页回收</strong><br />
统一将空白页挪到文件末端，删除空白页并截短数据库文件。
</li>
</ul>
<p>Fill Percent参数的引入，丰富了用户Vacuum操作的手段。在不同情况下用户可以选择不同的Fill Percent参数来精细化操作。典型的应用:</p>
<ul>
<li>对于一个正在工作的数据库，用一个非常低的Fill Percent值(比如1)来快速回收数据库中已存在的空页。因为这种情况下不存在页内数据搬移，数据库仅仅将现有的空页交换到尾部并截短，不会对现有数据加锁，速度会非常快。</li>
<li>对于一个处于关闭状态的数据库，用一个较高的Fill Percent值来尽可能地回收空间。</li>
</ul>
<p>这里有一个问题：假设用户设定目标Fill Percent值为80(%)，每条数据约占15%的空间。那么重排后该页应该存储5条数据(75%，更接近于目标值)还是6条数据(90%，更大填充率)呢。这是一个设计上的权衡选择。关于这一点，我们经过内部讨论后选择了前者。即令填充率接近于目标值，而不是尽可能地大。&#8221;Some applications want room to add data on the page, others want the pages packed as densely as possible&#8221;。在BDB开发者看来，页里面的数据和空闲空间都是重要的。合理的空闲空间可以让新数据利用现有的空闲空间，使得数据插入更加快速。</p>
<h2>4. 范例</h2>
<p>以下面是新Vacuum功能的范例片段，该程序实现了对指定数据库的循环增量Vaccum。</p>
<pre name="code" class="java:nogutter">
void vacuum()
{
	sqlite3 *db;
	char sql[4096];
	struct timeval t1, t2, t_begin;
	int rc, i;

	sqlite3_open(db_name, &#038;db);
	error_handler(db);

	/* 设置为手动增量Vacuum模式 */
	exec_sql(db, "PRAGMA auto_vacuum=INCREMENTAL;", 1);

	/* 每次增量Vacuum最多回收256页 */
	exec_sql(db, "PRAGMA bdbsql_vacuum_pages=256;", 1);

	/*目标页填充率为75% */
	exec_sql(db, "PRAGMA bdbsql_vacuum_fillpercent=75;", 1);

	/*循环做40次增量Vacuum */
	for (i = 0; i < 40; i++) {
		exec_sql(db, "PRAGMA incremental_vacuum;", 1);
		if (rc = sqlite3_errcode(db)) {
			fprintf(stderr, "[vacuum] ERROR: %s. ERRCODE: %d.n",
				sqlite3_errmsg(db), rc);
		}

		/* 获得数据库文件大小 */
		get_filesize(db_name);

		/* 睡眠一小段时间以减轻Vacuum对数据库的IO压力 */
		sqlite3_sleep(100);
	}

	cleanup(db);
}
</pre>
<h2>5. 结束语</h2>
<p>以上我们介绍了5.2 Vacuum的新功能并给出了一个范例。欢迎继续关注!</p>
<p>官方资料：<a href="http://download.oracle.com/docs/cd/E17076_02/html/bdb-sql/changedpragmas.html#auto_vacuum">Auto Vacuum</a>, <a href="http://download.oracle.com/docs/cd/E17076_02/html/bdb-sql/changedpragmas.html#incremental_vacuum">Incremental Vacuum</a>, <a href="http://download.oracle.com/docs/cd/E17076_02/html/bdb-sql/addedpragmas.html#bdbsql_vacuum_fillpercent">Vacuum Fillpercent</a>, <a href="http://download.oracle.com/docs/cd/E17076_02/html/bdb-sql/addedpragmas.html#bdbsql_vacuum_pages">Vacuum pages</a></p>
<p>BDB Blog：<a href="http://www.bdbchina.com">www.bdbchina.com</a><br />
BDB微博：<a href="http://weibo.com/bdbchina">http://weibo.com/bdbchina</a><br />
个人微博：<a href="http://weibo.com/2153755234">http://weibo.com/2153755234</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.bdbchina.com/2011/07/berkeley-db-sql-5-2%e6%96%b0vacuum%e5%8a%9f%e8%83%bd%e7%ae%80%e4%bb%8b/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Berkeley DB 5.2 正式发布</title>
		<link>http://www.bdbchina.com/2011/06/berkeley-db-5-2-%e6%ad%a3%e5%bc%8f%e5%8f%91%e5%b8%83/</link>
		<comments>http://www.bdbchina.com/2011/06/berkeley-db-5-2-%e6%ad%a3%e5%bc%8f%e5%8f%91%e5%b8%83/#comments</comments>
		<pubDate>Thu, 16 Jun 2011 10:49:52 +0000</pubDate>
		<dc:creator>linchunsun</dc:creator>
				<category><![CDATA[Berkeley DB]]></category>
		<category><![CDATA[Linchun Sun]]></category>

		<guid isPermaLink="false">http://www.bdbchina.com/?p=1540</guid>
		<description><![CDATA[经过9个月的紧张开发，Berkeley DB（下文简称BDB）于2011年6月15日正式发布了最新版本，版本号为Oracle Berkeley DB 11gR2 (11.2.5.2.28)。
从上世纪80年代第一个版本诞生至今，BDB一直扮演着嵌入式数据库领域领头羊的角色。由于具备了强大的性能，极度的易用性和良好的稳定性，BDB成为这个世界上最受欢迎的嵌入式数据库，并被广泛应用于从路由器到浏览器到操作系统等等计算机系统的方方面面之中,为用户带来了巨大的价值。下面，就让我们一起来揭开Berkeley DB 5.2.28（以下简称BDB5.2）的神秘面纱，看看这个最新版本的BDB将为开发者带来了哪些激动人心的新特性。
【新的访问方法 (Heap Access Method)】
在保留原有的btree，hash， recno和queue这四种访问方法的基础上，BDB5.2新增了heap 访问方法。Heap 访问方法通过复用删除数据所释放的空间，将数据库的大小控制在一个限定的范围内，有效的提高了空间利用率。它适用于存储容量受限的设备或对数据库文件大小有严格限制的环境，以及插入密集型的应用程序。比如可用来做中间服务器的静态图片缓存。
【动态资源管理 (Dynamic Resource Management)】
BDB5.2中，开发者无需再显式指定每种系统资源（如lock，locker等）的上限并在程序开始时一次性分配；BDB5.2将在程序运行过程中动态分配这些资源。资源的分配将根据实际的使用情况动态增长。
【扩展的高可用性 (SQL support for HA/replication) 】
BDB5.2为SQL接口也增加高可用性支持。开发者可以在多个节点上通过SQL HA来构建一个数据库集群，从而扩展了计算能力。
【扩展的Sequence (SQL support for Sequence)】
BDB5.2的SQL 接口引入了Sequence的支持，允许用户使用SQL语句生成序列， 并提供事务保护。
【灵活的高可用性管理 (Group Membership) 】
BDB5.2引入了新的组管理机制，允许用户动态地向组(Replication Group)里添加或者删除结点。系统将自动调整和维护组的大小。
【新增的db_tuner工具  (db_tuner)】
BDB5.2新增了一个db_tuner工具，可以辅助用户选择合适的page size，提升程序的性能。
除此之外，秉承我们一贯的为用户提供最高性能，最灵活的嵌入式数据库的理念，最新的BDB5.2 还修正了上一个版本中存在的各种问题，并对原有的多项功能进行了增强。更多详情，参见这里。
您可以通过 BDB下载页面下载并体验最新的BDB5.2. 如果您有任何问题，欢迎通过我们的博客或者BerkeleyDB的新浪微博留言，也欢迎通过邮件联系我们。
]]></description>
			<content:encoded><![CDATA[<p>经过9个月的紧张开发，Berkeley DB（下文简称BDB）于2011年6月15日正式发布了最新版本，版本号为Oracle Berkeley DB 11gR2 (11.2.5.2.28)。</p>
<p>从上世纪80年代第一个版本诞生至今，BDB一直扮演着嵌入式数据库领域领头羊的角色。由于具备了强大的性能，极度的易用性和良好的稳定性，BDB成为这个世界上最受欢迎的嵌入式数据库，并被广泛应用于从路由器到浏览器到操作系统等等计算机系统的方方面面之中,为用户带来了巨大的价值。下面，就让我们一起来揭开Berkeley DB 5.2.28（以下简称BDB5.2）的神秘面纱，看看这个最新版本的BDB将为开发者带来了哪些激动人心的新特性。</p>
<p>【<a href="http://download.oracle.com/docs/cd/E17076_02/html/installation/upgrade_11gr2_52_heap.html">新的访问方法</a> (Heap Access Method)】</p>
<p>在保留原有的btree，hash， recno和queue这四种访问方法的基础上，BDB5.2新增了heap 访问方法。Heap 访问方法通过复用删除数据所释放的空间，将数据库的大小控制在一个限定的范围内，有效的提高了空间利用率。它适用于存储容量受限的设备或对数据库文件大小有严格限制的环境，以及插入密集型的应用程序。比如可用来做中间服务器的静态图片缓存。</p>
<p>【<a href="http://download.oracle.com/docs/cd/E17076_02/html/installation/upgrade_11gr2_52_dyn_env.html">动态资源管理</a> (Dynamic Resource Management)】</p>
<p>BDB5.2中，开发者无需再显式指定每种系统资源（如lock，locker等）的上限并在程序开始时一次性分配；BDB5.2将在程序运行过程中动态分配这些资源。资源的分配将根据实际的使用情况动态增长。</p>
<p>【<a href="http://download.oracle.com/docs/cd/E17076_02/html/installation/upgrade_11gr2_52_rep_sql.html">扩展的高可用性 </a>(SQL support for HA/replication) 】</p>
<p>BDB5.2为SQL接口也增加高可用性支持。开发者可以在多个节点上通过SQL HA来构建一个数据库集群，从而扩展了计算能力。</p>
<p>【<a href="http://download.oracle.com/docs/cd/E17076_02/html/installation/upgrade_11gr2_52_seq_sql.html">扩展的Sequence</a> (SQL support for Sequence)】</p>
<p>BDB5.2的SQL 接口引入了Sequence的支持，允许用户使用SQL语句生成序列， 并提供事务保护。</p>
<p>【<a href="http://download.oracle.com/docs/cd/E17076_02/html/installation/upgrade_11gr2_52_grp_mbr.html">灵活的高可用性管理</a> (Group Membership) 】</p>
<p>BDB5.2引入了新的组管理机制，允许用户动态地向组(Replication Group)里添加或者删除结点。系统将自动调整和维护组的大小。</p>
<p>【<a href="http://download.oracle.com/docs/cd/E17076_02/html/api_reference/C/db_tuner.html">新增的db_tuner工具 </a> (db_tuner)】</p>
<p>BDB5.2新增了一个db_tuner工具，可以辅助用户选择合适的page size，提升程序的性能。</p>
<p>除此之外，秉承我们一贯的为用户提供最高性能，最灵活的嵌入式数据库的理念，最新的BDB5.2 还修正了上一个版本中存在的各种问题，并对原有的多项功能进行了增强。更多详情，参见<a href="http://download.oracle.com/otndocs/products/berkeleydb/html/changelog_5_2.html">这里</a>。</p>
<p>您可以通过 BDB<a href="http://www.oracle.com/technetwork/database/berkeleydb/downloads/index.html">下载页面</a>下载并体验最新的BDB5.2. 如果您有任何问题，欢迎通过我们的博客或者<a href="http://www.weobo.com/bdbchina">BerkeleyDB的新浪微博</a>留言，也欢迎通过邮件联系我们。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bdbchina.com/2011/06/berkeley-db-5-2-%e6%ad%a3%e5%bc%8f%e5%8f%91%e5%b8%83/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>bdb开通新浪微博</title>
		<link>http://www.bdbchina.com/2011/05/bdb%e5%bc%80%e9%80%9a%e6%96%b0%e6%b5%aa%e5%be%ae%e5%8d%9a/</link>
		<comments>http://www.bdbchina.com/2011/05/bdb%e5%bc%80%e9%80%9a%e6%96%b0%e6%b5%aa%e5%be%ae%e5%8d%9a/#comments</comments>
		<pubDate>Mon, 30 May 2011 10:41:58 +0000</pubDate>
		<dc:creator>chaohuang</dc:creator>
				<category><![CDATA[Berkeley DB]]></category>
		<category><![CDATA[Berkeley DB JE]]></category>
		<category><![CDATA[Berkeley DB XML]]></category>
		<category><![CDATA[Chao Huang]]></category>
		<category><![CDATA[生活圆桌]]></category>
		<category><![CDATA[bdb]]></category>

		<guid isPermaLink="false">http://www.bdbchina.com/?p=1537</guid>
		<description><![CDATA[各位BDB中文博客的粉丝们，为了更好的和大家交互并分享BDB的消息，我们刚刚开通的新浪微博。微博地址为：
http://www.weibo.com/bdbchina
欢迎各位朋友添加关注并和我们分享信息。感谢大家的一直以来的支持。
备注： 由于工作比较忙（很少看博客评论），我们推荐大家使用新浪微博和我们互动，从而可以得到更及时、有效的反馈。
Oracle Berkeley DB 中国开发团队
]]></description>
			<content:encoded><![CDATA[<p>各位BDB中文博客的粉丝们，为了更好的和大家交互并分享BDB的消息，我们刚刚开通的新浪微博。微博地址为：<a title="http://weibo.com/bdbchina" href="http://www.weibo.com/bdbchina" target="_blank"></a></p>
<p><a title="http://weibo.com/bdbchina" href="http://www.weibo.com/bdbchina" target="_blank">http://www.weibo.com/bdbchina</a></p>
<p>欢迎各位朋友添加关注并和我们分享信息。感谢大家的一直以来的支持。</p>
<p><em><strong>备注： 由于工作比较忙（很少看博客评论），我们推荐大家使用新浪微博和我们互动，从而可以</strong></em><em><strong>得到</strong></em><em><strong>更及时、有效的反馈。</strong></em></p>
<p>Oracle Berkeley DB 中国开发团队</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bdbchina.com/2011/05/bdb%e5%bc%80%e9%80%9a%e6%96%b0%e6%b5%aa%e5%be%ae%e5%8d%9a/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>BDB深圳新增两个职位</title>
		<link>http://www.bdbchina.com/2011/04/bdb%e6%b7%b1%e5%9c%b3%e6%96%b0%e5%a2%9e%e4%b8%a4%e4%b8%aa%e8%81%8c%e4%bd%8d/</link>
		<comments>http://www.bdbchina.com/2011/04/bdb%e6%b7%b1%e5%9c%b3%e6%96%b0%e5%a2%9e%e4%b8%a4%e4%b8%aa%e8%81%8c%e4%bd%8d/#comments</comments>
		<pubDate>Fri, 08 Apr 2011 07:54:42 +0000</pubDate>
		<dc:creator>chaohuang</dc:creator>
				<category><![CDATA[Berkeley DB]]></category>
		<category><![CDATA[Chao Huang]]></category>
		<category><![CDATA[bdb]]></category>

		<guid isPermaLink="false">http://www.bdbchina.com/?p=1532</guid>
		<description><![CDATA[Oracle(深圳)招聘嵌入式数据库研发工程师
Oracle公司 Berkeley DB (简称BDB) 是业界知名的嵌入式数据库，目前拥有开源和商业两种使用许可。BDB被广泛应用于各种场合，从小型的手持设备（如手机）到大型的分布式应用（如云存储）都可以找到BDB的身影。
BDB产品研发团队在全球拥有一批资深工程师，某些工程师有超过20年的数据库开发经验。2007年，BDB在深圳成立了中国研发团队，组内工程师均毕业于国内和香港著名高校。
本次BDB产品研发团队面向社会招聘如下两个职位：
1. 数据库核心开发工程师（1人）；
2. 数据同步服务器（Oracle Mobile Server） 开发工程师（1人）。
两个职位的工作地点均在深圳，薪酬优厚。感兴趣的朋友请发简历至：chao.huang[at]oracle.com
职位1：数据库核心开发工程师（1人）
工作职责：
- 负责 Berkeley 数据库的性能优化和新功能开发工作；
- 负责 Berkeley 数据库分布式和云计算架构的设计和开发工作；
- 负责 Berkeley 数据库测试和QA工作；
- 协助销售团队解决客户技术问题。
职位要求：
- 熟悉一项或多项项目开发流程：项目规划和协调，新功能设计和实现，产品测试和QA，产品发布；
- 熟练掌握一种或多种编程语言（C，C++ 或者Java），熟悉一种或多种操作系统：Linux，Windows，Android等；
- 对SQL语言和数据库内核有较深入理解者优先，包括缓存管理，索引，日志，恢复，并发控制等等。
职位2：Oracle Mobile Server 开发工程师（1人） 
工作职责：
- 参与Oracle Mobile Server的新功能开发、测试与性能优化；
- 协助Oracle Mobile Server软件发布。
- 为客户在使用过程中遇到的问题提供解决方案。
职位要求：
- 精通J2EE，SQL和PL/SQL的开发与测试。
- 熟练掌握一种或多种编程语言（C，C++ 或者Java），熟悉一种或多种操作系统：如Linux，Windows，Android；
- 有系统性能调优，SQL调优，Oracle数据库调优和Web/APP服务器调优经验者优先。
两个职位均要求有较好的英语读写能力，以及具有追求卓越的热情。除了参与产品本身的研发，也将有机会协助销售团队与中国的潜在 客户进行沟 通，解决客户所遇到的技术问题。目前，Berkeley数据库在中国市场（甚至是整个 亚太地区）的需求不断增大。加入我们，您可以通过 您的努力让我们的产品越来 越好，从而占领越来越多的市场。可以说，这是一份具有很大的挑战性，但是又是 充满乐趣的工作岗位！期待您的加入。

Oracle Berkeley DB is a family of embeddable database engines available [...]]]></description>
			<content:encoded><![CDATA[<p><span style="text-decoration: underline;">Oracle</span><span style="text-decoration: underline;">(深圳)招聘嵌入式数据库研发工程师</span></p>
<p>Oracle公司 Berkeley DB (简称BDB) 是业界知名的嵌入式数据库，目前拥有开源和商业两种使用许可。BDB被广泛应用于各种场合，从小型的手持设备（如手机）到大型的分布式应用（如云存储）都可以找到BDB的身影。</p>
<p>BDB产品研发团队在全球拥有一批资深工程师，某些工程师有超过20年的数据库开发经验。2007年，BDB在深圳成立了中国研发团队，组内工程师均毕业于国内和香港著名高校。</p>
<p>本次BDB产品研发团队面向社会招聘如下两个职位：<br />
1. 数据库核心开发工程师（1人）；<br />
2. 数据同步服务器（Oracle Mobile Server） 开发工程师（1人）。</p>
<p>两个职位的工作地点均在深圳，薪酬优厚。感兴趣的朋友请发简历至：<span style="text-decoration: underline;">chao.huang[at]oracle.com</span></p>
<p><strong>职位</strong><strong>1</strong><strong>：数据库核心开发工程师（</strong><strong>1</strong><strong>人）</strong></p>
<p>工作职责：<br />
- 负责 Berkeley 数据库的性能优化和新功能开发工作；<br />
- 负责 Berkeley 数据库分布式和云计算架构的设计和开发工作；<br />
- 负责 Berkeley 数据库测试和QA工作；<br />
- 协助销售团队解决客户技术问题。<br />
职位要求：<br />
- 熟悉一项或多项项目开发流程：项目规划和协调，新功能设计和实现，产品测试和QA，产品发布；<br />
- 熟练掌握一种或多种编程语言（C，C++ 或者Java），熟悉一种或多种操作系统：Linux，Windows，Android等；<br />
- 对SQL语言和数据库内核有较深入理解者优先，包括缓存管理，索引，日志，恢复，并发控制等等。</p>
<p><strong>职位</strong><strong>2</strong><strong>：</strong><strong>Oracle Mobile Server </strong><strong>开发工程师（</strong><strong>1</strong><strong>人）</strong><strong> </strong></p>
<p>工作职责：<br />
- 参与Oracle Mobile Server的新功能开发、测试与性能优化；<br />
- 协助Oracle Mobile Server软件发布。<br />
- 为客户在使用过程中遇到的问题提供解决方案。<br />
职位要求：<br />
- 精通J2EE，SQL和PL/SQL的开发与测试。<br />
- 熟练掌握一种或多种编程语言（C，C++ 或者Java），熟悉一种或多种操作系统：如Linux，Windows，Android；<br />
- 有系统性能调优，SQL调优，Oracle数据库调优和Web/APP服务器调优经验者优先。</p>
<p>两个职位均要求有较好的英语读写能力，以及具有追求卓越的热情。除了参与产品本身的研发，也将有机会协助销售团队与中国的潜在 客户进行沟 通，解决客户所遇到的技术问题。目前，Berkeley数据库在中国市场（甚至是整个 亚太地区）的需求不断增大。加入我们，您可以通过 您的努力让我们的产品越来 越好，从而占领越来越多的市场。可以说，这是一份具有很大的挑战性，但是又是 充满乐趣的工作岗位！期待您的加入。<br />
<span id="more-1532"></span></p>
<p>Oracle Berkeley DB is a family of embeddable database engines available under a dual license (Open source and commercial license). Berkeley DB is very popular, and is widely used in a variety of commercial as well as open source applications ranging from hand-held devices like cell phones to large, mission critical applications.</p>
<p>The Oracle Berkeley DB group is looking for one <strong><span style="text-decoration: underline;">Database Kernel Developer</span></strong> and one <strong><span style="text-decoration: underline;">Oracle Mobile Server Developer</span></strong> to join the development group in Shenzhen, China. The salary is negotiable.  We welcome junior level up to principal level of applicants to apply for our openings. If you want to join us, please send your resume to:  chao.huang[at]oracle.com.</p>
<p>We have a highly talented and experienced group of engineers distributed world-wide, several with more than twenty years of experience in the database industry. We have a small, but excellent development team in Shenzhen, China.</p>
<p><strong>Position1</strong><strong>： Database Kernel Developer </strong></p>
<p>Job Responsibilities：<br />
- Berkeley DB performance tuning and new feature implementation;<br />
- Berkeley DB distributed and cloud computing architecture designing and implementation;<br />
- Berkeley DB testing and QA;<br />
- Assist in providing technical support for customers.<br />
Job Requirements:<br />
- Experience in one or more aspects of product development: project planning and coordination, new features design and implementation, testing and QA, product release is highly desirable.<br />
- Expertise in one or more programming languages (C, C++ or Java) and familiarity with one or more operating system platforms like Linux, Windows, Android is required.<br />
- Excellent knowledge of SQL and database internals, including buffer management, indexing, logging, recovery, concurrency control, etc will be a strong plus.<br />
- Good interpersonal and communication (English and Chinese) skills are critical. The Berkeley DB development group has a very informal but effective and results-oriented work environment; a good cultural fit is important.</p>
<p><strong>Position2</strong><strong>：Oracle Mobile Server Developer</strong></p>
<p>Job Responsibilities:<br />
- Work on development, test and improvement of Oracle Mobile Sync Server product;<br />
- Assist in releasing of Oracle Mobile Sync Server software;<br />
- Assist in providing technical support for customers.<br />
Job Requirements:<br />
- Familiar with J2EE, SQL and PL/SQL development and testing.<br />
- Expertise in one or more programming languages (C, C++ or Java) and familiarity with one or more operating system platforms like Linux, Windows, Android is required.<br />
- Experience in Performance Profiling, Tuning SQL, Tuning Oracle Database and Tuning Web/APP Server will be an advantage.</p>
<p>Both positions require good written and verbal communication skills, and passions for excellence. Besides the opportunity to enhance the Berkeley DB family of products, there is also an opportunity to assist the local sales team with customers and prospects in China. There is a growing demand for products like Berkeley DB in the China market (and APAC in general) and the ideal candidate will be able to assist and make a difference! It&#8217;s truly a demanding, but fun opportunity!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bdbchina.com/2011/04/bdb%e6%b7%b1%e5%9c%b3%e6%96%b0%e5%a2%9e%e4%b8%a4%e4%b8%aa%e8%81%8c%e4%bd%8d/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Using Oracle Berkeley DB as a NoSQL Data Store</title>
		<link>http://www.bdbchina.com/2011/02/using-oracle-berkeley-db-as-a-nosql-data-store/</link>
		<comments>http://www.bdbchina.com/2011/02/using-oracle-berkeley-db-as-a-nosql-data-store/#comments</comments>
		<pubDate>Thu, 24 Feb 2011 03:37:59 +0000</pubDate>
		<dc:creator>chaohuang</dc:creator>
				<category><![CDATA[Berkeley DB]]></category>
		<category><![CDATA[Berkeley DB JE]]></category>
		<category><![CDATA[Berkeley DB XML]]></category>
		<category><![CDATA[Chao Huang]]></category>
		<category><![CDATA[cloud]]></category>
		<category><![CDATA[nosql]]></category>

		<guid isPermaLink="false">http://www.bdbchina.com/?p=1527</guid>
		<description><![CDATA[

Using Oracle Berkeley DB as a NoSQL Data Store
By Shashank Tiwari
Learn why and how Oracle Berkeley DB can bring NoSQL benefits to your app.
Published February 2011
“NoSQL” is the new popular buzzword among developers, architects and even technology managers. However, despite the term&#8217;s newfound popularity, surprisingly there is no universally agreed-upon definition for it.
Generally, any database [...]]]></description>
			<content:encoded><![CDATA[<div>
<div>
<h2>Using Oracle Berkeley DB as a NoSQL Data Store</h2>
<p><em>By Shashank Tiwari</em></p>
<p><strong>Learn why and how Oracle Berkeley DB can bring NoSQL benefits to your app.</strong></p>
<p>Published February 2011</p>
<p>“NoSQL” is the new popular buzzword among developers, architects and even technology managers. However, despite the term&#8217;s newfound popularity, surprisingly there is no universally agreed-upon definition for it.</p>
<p>Generally, any database that isn’t RDBMS, upholds schema-less structures, is generally relaxed on ACID transactions, and promises high availability and support for large data sets in horizontally scaled environments is popularly categorized as a “NoSQL data store”. Given that these common features often seem in direct contrast to those of a good old RDBMS, some people propose <em>non-relational</em>, perhaps shortened as NonRel, as a more appropriate term than NoSQL.</p>
<p>Regardless, while the definitional conflict continues, many have begun to realize the benefits of NoSQL data stores by including them in their application stack. The rest are keeping a close watch and evaluating if NoSQL is right for them.</p>
<p><span id="more-1527"></span></p>
<p>The growth of NoSQL as a category has also led to the emergence of a number of new data stores. Some of these new NoSQL products are good at persisting JSON-like documents, some are sorted ordered column-family stores, and others persist distributed key-value pairs. While newer products are exciting and offer many nice features, a few existing ones rise up to deliver the new promise as well.</p>
<p>One such data store is <a href="http://www.oracle.com/technetwork/database/berkeleydb/overview/index.html">Oracle Berkeley DB</a>. In this article I will illustrate and explain why and how Berkeley DB can be included in the stack as a NoSQL solution. The article focuses exclusively on Berkeley DB’s NoSQL-centric features and thus does not exhaustively cover all of Berkeley DB’s capabilities and idiosyncrasies.</p>
<h3>Berkeley DB Essentials</h3>
<p>Fundamentally a key-value store, Berkeley DB comes in three distinct flavors:</p>
<ul>
<li>Berkeley DB – key-value store programmed in C. (Berkeley DB official documentation uses the term <em>key-data</em> in place of key-value.) This is the &#8220;classic&#8221; flavor.</li>
<li>Berkeley DB Java Edition (JE) – key-value store re-written in Java. Can easily be incorporated into a Java stack.</li>
<li>Berkeley DB XML – Written in C++, this version wraps the key-value store to behave as an indexed and optimized XML storage system.</li>
</ul>
<p>(Note: Although this article does not expressly cover Berkeley DB JE or Berkeley DB XML, it does include examples that use the Java API and the Java-based persistence frameworks to illustrate the capabilities of Berkeley DB.)</p>
<p>Simple as it may be at its core, Berkeley DB can be configured to provide concurrent non-blocking access or support transactions, scaled out as a highly available cluster of master-slave replicas, or in a number of other ways.</p>
<p>Berkeley DB is a pure storage engine that makes no assumptions about an implied schema or structure to the key-value pairs. Therefore, Berkeley DB easily allows for higher level API, query, and modeling abstractions on top of the underlying key-value store. This facilitates fast and efficient storage of application specific data, without the overhead of translating it into an abstracted data format. The flexibility offered by this simple, yet elegant design, makes it possible to store both structured and semi-structured data in Berkeley DB.</p>
<p>Berkeley DB can run as an in-memory store to hold small amounts of data or it can be configured as a large data store, with a fast in-memory cache. Multiple databases can be set up in a single physical install with the help of a higher-level abstraction, called <em>environment</em>. One environment can have multiple databases. You need to open an environment and then a database to write data to it or read data from it. It’s advised that you close a database and the environment when you have completed your interactions to optimally use resources.</p>
<p>Each item in a database is a key-value pair. The key is typically unique but you could have duplicates. A Value is accessed using a key. A retrieved value can be updated and saved back to the database. Multiple values are accessed and iterated over using a cursor. Cursors allow you to loop through the collection of values and manipulate them one at a time. Transactions and concurrent access are additionally supported.</p>
<p>The key of a key-value pair almost always serves as the primary key, which is indexed. Other properties within the value could serve as secondary indexes. Secondary indexes are maintained separately in a secondary database. The main database, which has the key-value pairs, is therefore also sometimes referred to as the primary database.</p>
<p>Berkeley DB runs as an in-process data store, so you statically or dynamically link to it when accessing it using the C, C++, C#, Java or scripting language APIs from a corresponding program.</p>
<p>With that whirlwind introduction, the following section describes Berkeley DB in the context of its NoSQL-centric features.</p>
<h3>Fluid Schema</h3>
<p>The first benefit of a NoSQL store is its relaxed attitude toward well-defined database schemas. Let us see how Berkeley DB fares on this feature.</p>
<p>To appreciate Berkeley DB’s capabilities, I suggest you take it for a spin. Therefore, it is recommended that you download and install both Berkeley DB and Berkeley DB JE on your machine so you can try some examples yourself and follow along with the rest of the illustrations in this article. Download links and installation instructions are available online <a href="http://www.oracle.com/technetwork/database/berkeleydb/downloads/index.html">here</a>. (I compiled Berkeley DB with &#8211;enable-java, &#8211;enable-sql, and &#8211;prefix=/usr/local for this article.) The fundamental concepts that relate to storage, access mechanisms and the API don’t vary much between Berkeley DB and Berkeley DB JE so most things I cover next apply equally well to both.</p>
<p>Berkeley DB itself imposes little restrictions on the data items beyond it being a collection of key-value pairs. This allows applications to flexibly use Berkeley DB to manage data in a variety of formats, including SQL, XML and Java objects. You can access data in Berkeley DB via the base API, the SQL API, the Java Collections API, and the Java Direct Persistence Layer (DPL). It allows a few different storage configurations: B-Tree, Hash, Queue, and Recno. (The Berkeley DB documentation refers to the different storage mechanisms as “access methods”. Hash, Queue, and Recno access methods are available only in Berkeley DB and not in Berkeley DB JE or Berkeley DB XML.)</p>
<p>Depending on your specific use case, you could choose an access mechanism and a storage configuration. This choice of a particular access method and a storage configuration can affect schema. To understand the impact of the choices, you need to first understand what they are. I cover the access methods and storage configurations next.</p>
<h4>Using the Base API</h4>
<p>The Base API is a low-level API that allows you to store, retrieve and update data, the key-value pairs. This API is similar across different language bindings. Therefore the Base API for C, C++ and Java are quite the same. DPL and the Java Collections API, on the other hand, are only offered as an abstraction in the Java API.</p>
<p>The Base API puts, gets and deletes key-value pairs. Both the key and the value are an array of bytes. All key and data values get serialized to byte arrays before they are stored. One could use Java’s built-in serializer or Berkeley DB’s BIND API to serialize various data types to byte arrays. Java’s built-in serializer is typically a slow performer so one must go in favor of the BIND API. (The jvm-serializers project benchmarks various alternative serializers and is a good reference point to <a href="https://github.com/eishay/jvm-serializers/wiki/">analyze relative performance</a> among different serialization mechanisms in the JVM.) The BIND API avoids redundantly storing the class information with every serialized class and instead puts that information in a separate database. Potentially, you could makes things faster by writing your own <a href="http://download.oracle.com/docs/cd/E17076_02/html/gsg/JAVA/bindAPI.html#customTuple.">custom tuple binding</a> to improve the BIND API performance.</p>
<p>As an elementary example, you can have a data value defined as follows:</p>
<pre>import java.io.Serializable;
public class DataValue implements Serializable {
    private long prop1;
    private double prop2;

    DataValue() {
      prop1 = 0;
      prop2 = 0.0;
    }

    public void setProp1(long data) {
      prop1 = data;
    }

    public long getProp1() {
      return prop1;
    }

    public void setProp2(double data) {
      prop2 = data;
    }

    public double getProp2() {
      return prop2;
    }
}</pre>
<p>Now, you can store this data value using two databases, one to store the value with a key and another to store the class information.</p>
<p>The data is stored using four distinct steps:</p>
<ol>
<li>First a second database, apart from the one to store key-value pairs, is configured to store class data as follows:
<pre>Database aClassDB = new Database("classDB", null, aDbConfig);</pre>
</li>
<li>Then a class catalog is instantiated as follows:
<pre>StoredClassCatalog storedClassCatalog = new StoredClassCatalog(aClassDb);</pre>
</li>
<li>A serial entry binding is established like so:
<pre>EntryBinding binding = new SerialBinding(storedClassCatalog, DataValue.class);</pre>
</li>
<li>Finally, a DataValue instance like so:
<pre>DataValue val = new DataValue();
val.setProp1(123456789L);
val.setProp2(1234.56789);</pre>
<p>is mapped to a Berkeley DB DatabaseEntry, which serves as a wrapper for both the key and value, using the binding you just created as follows:</p>
<pre>DatabaseEntry deKey = new DatabaseEntry(aKey.getBytes("UTF-8"));
DatabaseEntry deVal = new DatabaseEntry();
binding.objectToEntry(val, deVal);</pre>
</li>
</ol>
<p>Now you are ready to put the key-value pair in Berkeley DB.</p>
<p>The base API supports a few variants of the put and get methods, to allow or dis-allow duplicates and overwrites. (The intent of neither this example nor the article is to teach you the detailed syntax or semantics of using the base API so I will not get into further details; see the doc <a href="http://www.oracle.com/technetwork/database/berkeleydb/documentation/index.html">here</a>.) An important takeaway is that the base API allows for low-level manipulation and custom serialization around storing, retrieving and deleting key-value pairs.</p>
<p>If you prefer to interact with Berkeley DB with a higher level API, then you should use DPL.</p>
<h4>Using DPL</h4>
<p>Direct Persistence Layer (DPL) provides familiar Java persistence framework semantics for manipulating objects. You can treat Berkeley DB as an entity store where objects are persisted, retrieved to be updated and deleted. DPL uses annotations to mark a class as an @Entity. Associated classes, which get stored with an Entity, are annotated as @Persistent. Specific properties or variables can be annotated as @PrimaryKey and @SecondaryKey. A simple Entity could be as follows:</p>
<pre>@Entity
public class AnEntity {

    @PrimaryKey
    private int myPrimaryKey;

    @SecondaryKey(relate=ONE_TO_ONE)
    private String mySecondaryKey;
    ...
}</pre>
<p>DPL imposes the class definition as a well-defined schema. From the base API we know that such a conformance to schema is not a requirement for Berkeley DB. For some use cases, however, formal entity definitions are helpful and provide a structured approach to data modeling.</p>
<h4>Storage Configuration</h4>
<p>As mentioned previously, key-value pairs can be stored in four different types of data structures: B-Tree, Hash, Queue and Recno. Let’s see how they stack up.</p>
<ul>
<li><strong>B-Tree. </strong>A B-tree needs little introduction but if you do need to review its definition then read the Wikipedia page on B-Tree, available online at <a href="http://en.wikipedia.org/wiki/B-tree">http://en.wikipedia.org/wiki/B-tree</a>. It’s a balanced tree data structure that keeps its elements sorted and allows for fast sequential access, insertions and deletions. Key and values can be arbitrary data types. In Berkeley DB the B-tree access method allows duplicates. This is a good choice if you need complex data types as keys. It’s also a great choice if data access patterns lead to access of contiguous or neighboring records. B-Tree keeps a substantial amount of metadata to perform efficiently. Most Berkeley DB applications use the B-Tree storage configuration.</li>
<li><strong>Hash. </strong>Like the B-Tree a hash also allows complex types to be keys. Hashes have a more linear structure as compared to a B-Tree. Berkeley DB hash structures allow duplicates.While both a B-Tree and a hash support complex keys, a hash database usually outperforms a B-Tree when the data set far exceeds the amount of available memory. That is because a B-Tree keeps more metadata than a hash and a larger data set implies that the B-Tree metadata may not fit in the in-memory cache. In such an extreme situation the B-Tree metadata as well as the actual data record itself will often have to be fetched from files, which can cause multiple I/Os per operation. The hash access method is designed to minimize the I/Os required to access the data record and therefore in these extreme cases, may perform better than a B-Tree.</li>
<li><strong>Queue. </strong>A queue is a set of sequentially stores fixed length records. Keys are restricted to logical record numbers, which are integer types. Records are appended sequentially allowing for extremely fast writes. If you are impressed by Apache Cassandra’s fast writes by appending to logs then give Berkeley DB with queue access method a try and you wouldn’t be disappointed. Methods also allow reading and updating effectively from the head of the queue. A queue has additional support for row-level locking. This allows effective transactional integrity even in cases of concurrent processing.</li>
<li><strong>Recno. </strong>Recno is similar to a queue but allows variable length records. And like a queue, recno keys are restricted to integers.</li>
</ul>
<p>The different configurations allow you to store arbitrary types of data in a collection. Similar to NoSQL, there is no fixed schema, other than those imposed by your model. In the extreme situation, you are welcome to store disparate value types for two keys in a collection. Value types can be complex classes, which for the sake of argument could represent a JSON document, a complex data structure or a structured data set. The only restriction really is that the value should be serializable to a byte array. A single key or a single value can be as large as 4GB.</p>
<p>The possibility of secondary indexes allows filtering on the basis of value properties. The primary database does not store data in a tabular format and so non-existing properties are not stored for sparse data sets. A secondary index skips all key-value pairs that lack the property on which the index is created. In general the storage is compact and efficient.</p>
<h3>Support for Transactions</h3>
<p>Berkeley DB is a very flexible database that can turn many features on and off. Berkeley DB can run without transaction support or it could be compiled to support ACID transactional integrity. Perhaps, the malleable nature of Berkeley DB makes it a very appropriate data store for many situations. Transactional integrity is the least supported feature in a quintessential NoSQL data store. Berkeley DB, in highly available systems, that don’t expect ACID transactional compliance can turn transactions off and work like a typical NoSQL product. However, in others it could be flexible and support transactional integrity.</p>
<p>While I don’t intend to cover details on transactions, it’s worth noting that like traditional RDBMS systems, Berkeley DB enabled with transactions allows definition of transactional boundaries. Once committed, data is persisted to disk. To enhance performance, one can use non-durable commits, where writes are committed to in-memory log files and later synched with the underlying file systems. Isolation levels and locking mechanisms are also supported.</p>
<p>Before a database is closed a sync operation assures that persistent file copies have up-to-date in-memory information in the system. The combination of this sync operation and Berkeley DB&#8217;s transactional recovery subsystem (assuming that you have enabled transactions) ensure that the database is always returned to a consistent transactional state, even in the event of application or system failure.</p>
<h3>Large Data Sets</h3>
<p>Theoretically Berkeley DB has an upper bound of 256TB but in real life it’s usually bound by the size of the machine it runs on. At the time of this writing, Berkeley DB does not demonstrate support for extremely large files that span multiple machines with the help of distributed file systems. (Files larger than the size of a single node can be managed with the help of distributed file systems like the Hadoop Distributed File System, or HDFS.) Berkeley DB works better on local file systems than it does on network file systems. More accurately, Berkeley DB relies on the POSIX compliant attributes of a file system. For example, when Berkeley DB calls fsync() and the file system returns, Berkeley DB assumes that the data has been written to persistent media. For performance reasons, distributed file systems typically do not guarantee that a write has been completed all the way to the persistent media.</p>
<p>The maximum B-Tree depth supported is 255. Lengths of the key and value records are typically bound by the available memory.</p>
<h3>Horizontal Scale-out</h3>
<p>Berkeley DB replication follows a master-slave pattern. In such a pattern there is one master and multiple slaves or replicas. However, the selection of a master is not static and it’s recommended that the selection is not manual. All participants in a replication cluster go through an election process to choose the master. The one with the most up-to-date log records is the winner. If there is a tie, then priorities are used to select the master. The election process is based on an industry standard <a href="http://en.wikipedia.org/wiki/Paxos_algorithm">Paxos-compliant algorithm</a>.</p>
<p>Replication has numerous benefits including the following:</p>
<ul>
<li>Improves read performance – The availability of multiple replicated nodes to read data from improves the read performance drastically.</li>
<li>Improves reliability – The presence of replicated instances provides better failover options in times of node failure and data corruption.</li>
<li>Improves durability – You can relax durability guarantees on the master to avoid excessive write to disk operations, which typically involves expensive I/O. In a clustered environment the durability is enhanced by the fact that the write has been committed to multiple nodes, even if it’s not written to disk.</li>
<li>Improves availability – The presence of multiple nodes, along with asynchronous write to disk, makes it possible for replicas to keep serving operations even when the master is under heavy load.</li>
</ul>
<h3>Summary</h3>
<p>Berkeley DB undoubtedly qualifies as a robust and scalable NoSQL key-value store; the use of Berkeley DB as the underlying storage for Amazon’s <a href="http://www.allthingsdistributed.com/2007/10/amazons_dynamo.html">Dynamo</a>, <a href="http://project-voldemort.com/">Project Voldemort</a>, <a href="http://memcachedb.org/">MemcacheDB</a>, and <a href="http://www.geniedb.com/">GenieDB</a> is further evidence supporting this claim. There has been a little bit of FUD around Berkeley DB performance, especially in the wake of couple of comparative benchmarks published online:</p>
<ul>
<li><a href="http://www.dmo.ca/blog/benchmarking-hash-databases-on-large-data/">http://www.dmo.ca/blog/benchmarking-hash-databases-on-large-data/</a></li>
<li><a href="http://stackoverflow.com/questions/601348/berkeleydb-vs-tokyo-cabinet">http://stackoverflow.com/questions/601348/berkeleydb-vs-tokyo-cabinet</a></li>
</ul>
<p>However, there are many live systems that prove Berkeley DB’s strengths. Many of these systems, through careful tuning and application coding improvements, have achieved excellent scalability, throughput, and reliability results. Following the lead of those systems, Berkeley DB can certainly be used as a scalable NoSQL solution.</p>
<hr /><strong>Shashank Tiwari </strong>is Founder &amp; CEO of <a href="http://www.treasuryofideas.com/">Treasury of Ideas</a>, a technology driven innovation and value optimization company. As an experienced software developer and architect, he is adept in a multitude of technologies. He is an internationally recognized speaker, author and mentor. As an expert group member on a number of JCP (Java Community Process) specifications he has been actively participating in shaping the future of Java. He is also an common voice in the NoSQL and Cloud Computing space and a recognized expert in the RIA community.</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.bdbchina.com/2011/02/using-oracle-berkeley-db-as-a-nosql-data-store/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
Դ
