Author: dmeil
Date: Thu Aug 25 01:20:15 2011
New Revision: 1161352

URL: http://svn.apache.org/viewvc?rev=1161352&view=rev
Log:
HBASE-4251 book.xml (catalog info, reorg of schema design for rowkeys, reorg 
version info)

Modified:
    hbase/trunk/src/docbkx/book.xml

Modified: hbase/trunk/src/docbkx/book.xml
URL: 
http://svn.apache.org/viewvc/hbase/trunk/src/docbkx/book.xml?rev=1161352&r1=1161351&r2=1161352&view=diff
==============================================================================
--- hbase/trunk/src/docbkx/book.xml (original)
+++ hbase/trunk/src/docbkx/book.xml Thu Aug 25 01:20:15 2011
@@ -192,22 +192,23 @@ admin.enableTable(table);               
         i.e. you query one column family or the other but usually not both at 
the one time.
     </para>
   </section>
-  <section xml:id="timeseries">
-  <title>
-  Monotonically Increasing Row Keys/Timeseries Data
-  </title>
-  <para>
-      In the HBase chapter of Tom White's book <link 
xlink:url="http://oreilly.com/catalog/9780596521981";>Hadoop: The Definitive 
Guide</link> (O'Reilly) there is a an optimization note on watching out for a 
phenomenon where an import process walks in lock-step with all clients in 
concert pounding one of the table's regions (and thus, a single node), then 
moving onto the next region, etc.  With monotonically increasing row-keys 
(i.e., using a timestamp), this will happen.  See this comic by IKai Lan on why 
monotically increasing row keys are problematic in BigTable-like datastores:
+  <section xml:id="rowkey.design"><title>Rowkey Design</title>
+    <section xml:id="timeseries">
+    <title>
+    Monotonically Increasing Row Keys/Timeseries Data
+    </title>
+    <para>
+      In the HBase chapter of Tom White's book <link 
xlink:url="http://oreilly.com/catalog/9780596521981";>Hadoop: The Definitive 
Guide</link> (O'Reilly) there is a an optimization note on watching out for a 
phenomenon where an import process walks in lock-step with all clients in 
concert pounding one of the table's regions (and thus, a single node), then 
moving onto the next region, etc.  With monotonically increasing row-keys 
(i.e., using a timestamp), this will happen.  See this comic by IKai Lan on why 
monotonically increasing row keys are problematic in BigTable-like datastores:
       <link 
xlink:href="http://ikaisays.com/2011/01/25/app-engine-datastore-tip-monotonically-increasing-values-are-bad/";>monotonically
 increasing values are bad</link>.  The pile-up on a single region brought on
-      by monoticially increasing keys can be mitigated by randomizing the 
input records to not be in sorted order, but in general its best to avoid using 
a timestamp or a sequence (e.g. 1, 2, 3) as the row-key. 
-  </para>
+      by monotonically increasing keys can be mitigated by randomizing the 
input records to not be in sorted order, but in general its best to avoid using 
a timestamp or a sequence (e.g. 1, 2, 3) as the row-key. 
+    </para>
 
 
-  <para>If you do need to upload time series data into HBase, you should
-  study <link xlink:href="http://opentsdb.net/";>OpenTSDB</link> as a
-  successful example.  It has a page describing the <link xlink:href=" 
http://opentsdb.net/schema.html";>schema</link> it uses in
-  HBase.  The key format in OpenTSDB is effectively 
[metric_type][event_timestamp], which would appear at first glance to 
contradict the previous advice about not using a timestamp as the key.  
However, the difference is that the timestamp is not in the 
<emphasis>lead</emphasis> position of the key, and the design assumption is 
that there are dozens or hundreds (or more) of different metric types.  Thus, 
even with a continual stream of input data with a mix of metric types, the Puts 
are distributed across various points of regions in the table.
- </para>
+    <para>If you do need to upload time series data into HBase, you should
+    study <link xlink:href="http://opentsdb.net/";>OpenTSDB</link> as a
+    successful example.  It has a page describing the <link xlink:href=" 
http://opentsdb.net/schema.html";>schema</link> it uses in
+    HBase.  The key format in OpenTSDB is effectively 
[metric_type][event_timestamp], which would appear at first glance to 
contradict the previous advice about not using a timestamp as the key.  
However, the difference is that the timestamp is not in the 
<emphasis>lead</emphasis> position of the key, and the design assumption is 
that there are dozens or hundreds (or more) of different metric types.  Thus, 
even with a continual stream of input data with a mix of metric types, the Puts 
are distributed across various points of regions in the table.
+   </para>
   </section>
   <section xml:id="keysize">
       <title>Try to minimize row and column sizes</title>
@@ -231,8 +232,8 @@ admin.enableTable(table);               
                   the thread <link 
xlink:href="http://search-hadoop.com/m/hemBv1LiN4Q1/a+question+storefileIndexSize&amp;subj=a+question+storefileIndexSize";>a
 question storefileIndexSize</link>
                   up on the user mailing list.
        </para>
-       <para>Most frequently small inefficiencies don't matter all that much.  
Unfortunately,
-         this is a case where it does.  Whatever patterns are selected for 
ColumnFamilies, attributes, and rowkeys they could be repeated
+       <para>Most of the time small inefficiencies don't matter all that much. 
 Unfortunately,
+         this is a case where they do.  Whatever patterns are selected for 
ColumnFamilies, attributes, and rowkeys they could be repeated
        several billion times in your data</para>
        <section xml:id="keysize.cf"><title>Column Families</title>
          <para>Try to keep the ColumnFamily names as small as possible, 
preferably one character (e.g. "d" for data/default).
@@ -243,14 +244,33 @@ admin.enableTable(table);               
          to store in HBase.
          </para> 
        </section>
-       <section xml:id="keysize.row"><title>Row Key</title>
+       <section xml:id="keysize.row"><title>Rowkey Length</title>
          <para>Keep them as short as is reasonable such that they can still be 
useful for required data access (e.g., Get vs. Scan). 
          A short key that is useless for data access is not better than a 
longer key with better get/scan properties.  Expect tradeoffs
          when designing rowkeys.
          </para> 
        </section>
-  </section>
-  <section xml:id="schema.versions">
+    </section>
+    <section xml:id="reverse.timestamp"><title>Reverse Timestamps</title>
+    <para>A common problem in database processing is quickly finding the most 
recent version of a value.  A technique using reverse timestamps
+    as a part of the key can help greatly with a special case of this problem. 
 Also found in the HBase chapter of Tom White's book Hadoop:  The Definitive 
Guide (O'Reilly), 
+    the technique involves appending (<code>Long.MAX_VALUE - timestamp</code>) 
to the end of any key, e.g., [key][reverse_timestamp].
+    </para>
+    <para>The most recent value for [key] in a table can be found by 
performing a Scan for [key] and obtaining the first record.  Since HBase keys
+    are in sorted order, this key sorts before any older row-keys for [key] 
and thus is first.
+    </para>
+    <para>This technique would be used instead of using <xref 
linkend="schema.versions">HBase Versioning</xref> where the intent is to hold 
onto all versions
+    "forever" (or a very long time) and at the same time quickly obtain access 
to any other version by using the same Scan technique.
+    </para>
+    </section>
+    <section xml:id="changing.rowkeys"><title>Immutability of Rowkeys</title>
+    <para>Rowkeys cannot be changed.  The only way they can be "changed" in a 
table is if the row is deleted and then re-inserted.
+    This is a fairly common question on the HBase dist-list so it pays to get 
the rowkeys right the first time (and/or before you've 
+    inserted a lot of data).
+    </para>
+    </section>
+    </section>  <!--  rowkey design -->  
+    <section xml:id="schema.versions">
   <title>
   Number of Versions
   </title>
@@ -262,12 +282,14 @@ admin.enableTable(table);               
       stores different values per row by time (and qualifier).  Excess 
versions are removed during major
       compactions.  The number of versions may need to be increased or 
decreased depending on application needs.
   </para>
-  </section>
-  <section xml:id="schema.minversions">
-  <title>
-  Minimum Number of Versions
-  </title>
-  <para>Like number of row versions, the minimum number of row versions to 
keep is configured per column
+  <para>It is not recommended setting the number of versions to an exceedingly 
high level (e.g., hundreds or more) unless those old values are 
+  very dear to you because this will greatly increase StoreFile size. 
+  </para>
+    <section xml:id="schema.minversions">
+    <title>
+    Minimum Number of Versions
+    </title>
+    <para>Like number of row versions, the minimum number of row versions to 
keep is configured per column
       family via <link 
xlink:href="http://hbase.apache.org/apidocs/org/apache/hadoop/hbase/HColumnDescriptor.html";>HColumnDescriptor</link>.
       The default is 0, which means the feature is disabled.
       The minimum number of row versions parameter is used together with the 
time-to-live parameter and can be combined with the
@@ -276,16 +298,8 @@ admin.enableTable(table);               
       (where M is the value for minimum number of row versions, M&lt;=N).
       This parameter should only be set when time-to-live is enabled for a 
column family and must be less or equal to the 
       number of row versions.
-  </para>
-  </section>
-  <section xml:id="changing.rowkeys">
-  <title>
-  Immutability of Rowkeys
-  </title>
-  <para>Rowkeys cannot be changed.  The only way they can be "changed" in a 
table is if the row is deleted and then re-inserted.
-  This is a fairly common question on the HBase dist-list so it pays to get 
the rowkeys right the first time (and/or before you've 
-  inserted a lot of data).
-  </para>
+    </para>
+    </section>
   </section>
   <section xml:id="supported.datatypes">
   <title>
@@ -861,6 +875,64 @@ admin.enableTable(table);               
   <chapter xml:id="architecture">
     <title>Architecture</title>
 
+       <section xml:id="arch.catalog">
+        <title>Catalog Tables</title>
+         <para>
+     </para>
+         <section xml:id="arch.catalog.root">
+          <title>ROOT</title>
+          <para>-ROOT- keeps track of where the .META. table is.  The -ROOT- 
table structure is as follows: 
+       </para>
+       <para>Key:   
+            <itemizedlist>
+              <listitem>.META. region key (<code>.META.,,1</code>)</listitem>
+            </itemizedlist>
+       </para>
+       <para>Values:   
+            <itemizedlist>
+              <listitem><code>info:regioninfo</code> (serialized <link 
xlink:href="http://hbase.apache.org/apidocs/org/apache/hadoop/hbase/HRegionInfo.html";>HRegionInfo</link>
+               instance of .META.)</listitem>
+              <listitem><code>info:server</code> (server:port of the 
RegionServer holding .META.)</listitem>
+              <listitem><code>info:serverstartcode</code> (start-time of the 
RegionServer process holding .META.)</listitem>
+            </itemizedlist>
+       </para>
+          </section>
+         <section xml:id="arch.catalog.meta">
+          <title>META</title>
+          <para>The .META. table keeps a list of all regions in the system. 
The .META. table structure is as follows: 
+       </para>
+       <para>Key:   
+            <itemizedlist>
+              <listitem>Region key of the format (<code>[table],[region start 
key],[region id]</code>)</listitem>
+            </itemizedlist>
+       </para>
+       <para>Values:   
+            <itemizedlist>
+              <listitem><code>info:regioninfo</code> (serialized <link 
xlink:href="http://hbase.apache.org/apidocs/org/apache/hadoop/hbase/HRegionInfo.html";>
+              HRegionInfo</link> instance for this region)
+              </listitem>
+              <listitem><code>info:server</code> (server:port of the 
RegionServer containing this region)</listitem>
+              <listitem><code>info:serverstartcode</code> (start-time of the 
RegionServer process containing this region)</listitem>
+            </itemizedlist>
+       </para>
+       <para>When a table is in the process of splitting two other columns 
will be created, <code>info:splitA</code> and <code>info:splitB</code> 
+       which represent the two daughter regions.  The values for these columns 
are also serialized HRegionInfo instances.
+       After the region has been split eventually this row will be deleted.
+       </para>
+       <para>Notes on HRegionInfo:  the empty key is used to denote table 
start and table end.  A region with an empty start key
+       is the first region in a table.  If region has both an empty start and 
an empty end key, its the only region in the table
+       </para>
+       <para>In the (hopefully unlikely) event that programmatic processing of 
catalog metadata is required, see the
+         <link 
xlink:href="http://hbase.apache.org/apidocs/org/apache/hadoop/hbase/util/Writables.html#getHRegionInfo%28byte[]%29";>Writables</link>
 utility.
+       </para>
+          </section>
+          <section xml:id="arch.catalog.startup">
+           <title>Startup Sequencing</title>
+           <para>The META location is set in ROOT first.  Then META is updated 
with server and startcode values.
+           </para>
+           </section>     
+     </section>  <!--  catalog -->
+     
        <section xml:id="client">
         <title>Client</title>
      <para>The HBase client


Reply via email to