mirror of
https://github.com/yasuhirokimura/db18
synced 2026-06-08 18:29:23 +00:00
220 lines
8.1 KiB
HTML
220 lines
8.1 KiB
HTML
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||
<head>
|
||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||
<title>Key Design</title>
|
||
<link rel="stylesheet" href="gettingStarted.css" type="text/css" />
|
||
<meta name="generator" content="DocBook XSL Stylesheets V1.73.2" />
|
||
<link rel="start" href="index.html" title="Berkeley DB Programmer's Reference Guide" />
|
||
<link rel="up" href="bdb_slices.html" title="Chapter 13. Berkeley DB Slice Support" />
|
||
<link rel="prev" href="slice-apis.html" title="Slice APIs" />
|
||
<link rel="next" href="xa.html" title="Chapter 14. Distributed Transactions" />
|
||
</head>
|
||
<body>
|
||
<div xmlns="" class="navheader">
|
||
<div class="libver">
|
||
<p>Library Version 18.1.40</p>
|
||
</div>
|
||
<table width="100%" summary="Navigation header">
|
||
<tr>
|
||
<th colspan="3" align="center">Key Design</th>
|
||
</tr>
|
||
<tr>
|
||
<td width="20%" align="left"><a accesskey="p" href="slice-apis.html">Prev</a> </td>
|
||
<th width="60%" align="center">Chapter 13. Berkeley DB Slice Support</th>
|
||
<td width="20%" align="right"> <a accesskey="n" href="xa.html">Next</a></td>
|
||
</tr>
|
||
</table>
|
||
<hr />
|
||
</div>
|
||
<div class="sect1" lang="en" xml:lang="en">
|
||
<div class="titlepage">
|
||
<div>
|
||
<div>
|
||
<h2 class="title" style="clear: both"><a id="slice-keys"></a>Key Design</h2>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<p>
|
||
If your application does not perform transaction-protected
|
||
operations on multiple records, then you do not need to give
|
||
your keys any special consideration just because of slices. In
|
||
this case, use keys designed exactly as you would if you were
|
||
not using slices. The internal hashing algorithm will
|
||
automatically distribute your records evenly across your slices
|
||
based on the data that the hash finds in your keys.
|
||
</p>
|
||
<p>
|
||
However, if you <span class="emphasis"><em>do</em></span> want to perform atomic
|
||
operations on multiple records, then you do need to give your
|
||
key design some thought. This is because the slice feature
|
||
distributes your records across unique sub-environments. A
|
||
transaction can not cross environments, so you must design your
|
||
keys so that those records which you want to operation upon in
|
||
a single transaction are all placed in the same slice. You do
|
||
this by identifying the portion of your key with is
|
||
<span class="emphasis"><em>slice-relevant</em></span>.
|
||
</p>
|
||
<p>
|
||
For example, suppose your application contains information
|
||
about corporate personnel. To adequately represent each
|
||
employee in the corporation, you have the following record
|
||
types:
|
||
</p>
|
||
<div class="itemizedlist">
|
||
<ul type="disc">
|
||
<li>
|
||
<p>
|
||
Contact information, including the employee's name,
|
||
organization name, office number, phone number, and email
|
||
address.
|
||
</p>
|
||
</li>
|
||
<li>
|
||
<p>
|
||
A photograph of the employee (stored as an external file).
|
||
</p>
|
||
</li>
|
||
<li>
|
||
<p>
|
||
The employee's public key for digital signatures.
|
||
</p>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
<p>
|
||
For a non-sliced database, it would be enough to create keys
|
||
using employee ID and record type. That is, for an employee
|
||
with ID 6591, your database would contain three keys:
|
||
</p>
|
||
<div class="orderedlist">
|
||
<ol type="1">
|
||
<li>
|
||
<p>
|
||
6591;Contact
|
||
</p>
|
||
</li>
|
||
<li>
|
||
<p>
|
||
6591;Image
|
||
</p>
|
||
</li>
|
||
<li>
|
||
<p>
|
||
6591;Signature
|
||
</p>
|
||
</li>
|
||
</ol>
|
||
</div>
|
||
<p>
|
||
However, for a sliced database, there is no guarantee that
|
||
the three records using these keys would be placed in the same
|
||
slice. If they are not in the same slice, then put and get
|
||
operations for all three records cannot be wrapped in a single
|
||
transaction. Without a single transaction, you cannot operated
|
||
on these three records atomically.
|
||
</p>
|
||
<p>
|
||
Therefore, to support a sliced database, you need to identify a
|
||
portion of the key that will be identical between records that
|
||
you want to operate upon within a single transaction. In this
|
||
simple example, you can use the employee's ID to accomplish
|
||
this. That is, you must identify the
|
||
<span class="emphasis"><em>slice-relevant</em></span> portion of the key so that
|
||
DB knows what to use when dividing records across slices.
|
||
</p>
|
||
<p>
|
||
To identify the slice-relevant portion of the key, you define a
|
||
callback, wich you then set using the <a href="../api_reference/C/dbset_slice_callback.html" class="olink">DB->set_slice_callback()</a> method.
|
||
</p>
|
||
<pre class="programlisting">int
|
||
construct_slice_dbt(const DB *db, const DBT *key, DBT *slice)
|
||
{
|
||
/*
|
||
* key is the source key.
|
||
*
|
||
* slice is the DBT that we use to identify the slice-relevant
|
||
* portion the data in key.
|
||
*
|
||
* This example does not require lifting disjointed portions of
|
||
* key to create a slice key, so we can get away with simply
|
||
* setting slice->size to highlight the interesting portion of
|
||
* key's data.
|
||
*
|
||
*/
|
||
slice->data = key->data;
|
||
slice->size = 4;
|
||
return (0);
|
||
}
|
||
|
||
...
|
||
|
||
/*
|
||
* Opening the environment is routine so we skip it here for
|
||
* the sake of brevity. Assume we have created and opened an
|
||
* environment handle, dbenv.
|
||
*/
|
||
|
||
DB *dbp = NULL;
|
||
DB_TXN *txn = NULL;
|
||
u_int32_t open_flags;
|
||
int ret;
|
||
|
||
ret = db_create(&dbp, dbenv, 0);
|
||
if (ret != 0) {
|
||
/* db_create failed. handle error here */
|
||
}
|
||
|
||
|
||
open_flags = DB_CREATE | DB_THREAD | DB_AUTO_COMMIT;
|
||
|
||
/* Open the database with slice support. */
|
||
open_flags |= DB_SLICED;
|
||
|
||
/* Set the callback before opening the database */
|
||
ret = dbp->set_slice_callback(dbp, construct_slice_dbt);
|
||
if (ret != 0) {
|
||
/* callback set failed. handle error here */
|
||
}
|
||
|
||
ret = dbp->open(dbp,
|
||
NULL, /* Txn pointer */
|
||
"mydb.db", /* Database file name */
|
||
NULL, /* Logical database name */
|
||
DB_BTREE, /* Database is using btree access method */
|
||
open_flags, /* Open flags */
|
||
0); /* File mode. Using defaults. */
|
||
|
||
if (ret != 0) {
|
||
/* db open failed. handle error here */
|
||
} </pre>
|
||
<p>
|
||
After that, you can read and write to your database exactly as
|
||
you would if you were using a non-sliced database. Your
|
||
threaded workload will scale across cores much better than if
|
||
you use a non-sliced environment.
|
||
</p>
|
||
</div>
|
||
<div class="navfooter">
|
||
<hr />
|
||
<table width="100%" summary="Navigation footer">
|
||
<tr>
|
||
<td width="40%" align="left"><a accesskey="p" href="slice-apis.html">Prev</a> </td>
|
||
<td width="20%" align="center">
|
||
<a accesskey="u" href="bdb_slices.html">Up</a>
|
||
</td>
|
||
<td width="40%" align="right"> <a accesskey="n" href="xa.html">Next</a></td>
|
||
</tr>
|
||
<tr>
|
||
<td width="40%" align="left" valign="top">Slice APIs </td>
|
||
<td width="20%" align="center">
|
||
<a accesskey="h" href="index.html">Home</a>
|
||
</td>
|
||
<td width="40%" align="right" valign="top"> Chapter 14. Distributed Transactions </td>
|
||
</tr>
|
||
</table>
|
||
</div>
|
||
</body>
|
||
</html>
|