You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by st...@apache.org on 2013/04/06 08:08:58 UTC

svn commit: r1465200 [18/21] - in /hbase/hbase.apache.org/trunk: ./ book/ case_studies/ community/ configuration/ css/ developer/ getting_started/ images/ ops_mgt/ performance/ rpc/ schema_design/ security/ shell/ troubleshooting/ upgrading/

Modified: hbase/hbase.apache.org/trunk/rpc/apas03.html
URL: http://svn.apache.org/viewvc/hbase/hbase.apache.org/trunk/rpc/apas03.html?rev=1465200&r1=1465199&r2=1465200&view=diff
==============================================================================
--- hbase/hbase.apache.org/trunk/rpc/apas03.html (original)
+++ hbase/hbase.apache.org/trunk/rpc/apas03.html Sat Apr  6 06:08:56 2013
@@ -1,42 +1,42 @@
 <html><head>
       <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
-   <title>A.3.&nbsp;RPC</title><link rel="stylesheet" type="text/css" href="../css/freebsd_docbook.css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.76.1"><link rel="home" href="rpc.html" title="Appendix&nbsp;A.&nbsp;0.95 RPC Specification"><link rel="up" href="rpc.html" title="Appendix&nbsp;A.&nbsp;0.95 RPC Specification"><link rel="prev" href="apas02.html" title="A.2.&nbsp;TODO"><link rel="next" href="apas04.html" title="A.4.&nbsp;Notes"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">A.3.&nbsp;RPC</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="apas02.html">Prev</a>&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;<a accesskey="n" href="apas04.html">Next</a></td></tr></table><hr></div><div class="section" title="A.3.&nbsp;RPC"><div class="titlepage"><div><
 div><h2 class="title" style="clear: both"><a name="d746e51"></a>A.3.&nbsp;RPC</h2></div></div></div><p>The client will send setup information on connection establish.
+   <title>A.3.&nbsp;RPC</title><link rel="stylesheet" type="text/css" href="../css/freebsd_docbook.css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.76.1"><link rel="home" href="rpc.html" title="Appendix&nbsp;A.&nbsp;0.95 RPC Specification"><link rel="up" href="rpc.html" title="Appendix&nbsp;A.&nbsp;0.95 RPC Specification"><link rel="prev" href="apas02.html" title="A.2.&nbsp;TODO"><link rel="next" href="apas04.html" title="A.4.&nbsp;Notes"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">A.3.&nbsp;RPC</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="apas02.html">Prev</a>&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;<a accesskey="n" href="apas04.html">Next</a></td></tr></table><hr></div><div class="section" title="A.3.&nbsp;RPC"><div class="titlepage"><div><
 div><h2 class="title" style="clear: both"><a name="d800e51"></a>A.3.&nbsp;RPC</h2></div></div></div><p>The client will send setup information on connection establish.
       Thereafter, the client invokes methods against the remote server sending a protobuf Message and receiving a protobuf Message in response.
       Communication is synchronous.  All back and forth is preceded by an int that has the total length of the request/response.
       Optionally, Cells(KeyValues) can be passed outside of protobufs in follow-behind Cell blocks (because
       <a class="link" href="https://docs.google.com/document/d/1WEtrq-JTIUhlnlnvA0oYRLp0F8MKpEBeBSCFcQiacdw/edit#" target="_top">we can&#8217;t protobuf megabytes of KeyValues</a> or Cells).
       These CellBlocks are encoded and optionally compressed.</p><p></p><p>For more detail on the protobufs involved, see the
-      <a class="link" href="http://svn.apache.org/viewvc/hbase/trunk/hbase-protocol/src/main/protobuf/RPC.proto?view=markup" target="_top">RPC.proto</a> file in trunk.</p><div class="section" title="A.3.1.&nbsp;Connection Setup"><div class="titlepage"><div><div><h3 class="title"><a name="d746e65"></a>A.3.1.&nbsp;Connection Setup</h3></div></div></div><p>Client initiates connection.</p><div class="section" title="A.3.1.1.&nbsp;Client"><div class="titlepage"><div><div><h4 class="title"><a name="d746e70"></a>A.3.1.1.&nbsp;Client</h4></div></div></div><p>On connection setup, client sends a preamble followed by a connection header.
-      </p><div class="section" title="A.3.1.1.1.&nbsp;<preamble&gt;"><div class="titlepage"><div><div><h5 class="title"><a name="d746e75"></a>A.3.1.1.1.&nbsp;&lt;preamble&gt;</h5></div></div></div><pre class="programlisting">&lt;MAGIC 4 byte integer&gt; &lt;1 byte RPC Format Version&gt; &lt;1 byte auth type&gt;<sup>[<a name="d746e81" href="#ftn.d746e81" class="footnote">1</a>]</sup></pre><p>E.g.: HBas0x000x80 -- 4 bytes of MAGIC -- &#8216;HBas&#8217; -- plus one-byte of version, 0 in this case, and one byte, 0x80 (SIMPLE). of an auth type.</p></div><div class="section" title="A.3.1.1.2.&nbsp;<Protobuf ConnectionHeader Message&gt;"><div class="titlepage"><div><div><h5 class="title"><a name="d746e86"></a>A.3.1.1.2.&nbsp;&lt;Protobuf ConnectionHeader Message&gt;</h5></div></div></div><p>Has user info, and &#8220;protocol&#8221;, as well as the encoders and compression the client will use sending CellBlocks.
+      <a class="link" href="http://svn.apache.org/viewvc/hbase/trunk/hbase-protocol/src/main/protobuf/RPC.proto?view=markup" target="_top">RPC.proto</a> file in trunk.</p><div class="section" title="A.3.1.&nbsp;Connection Setup"><div class="titlepage"><div><div><h3 class="title"><a name="d800e65"></a>A.3.1.&nbsp;Connection Setup</h3></div></div></div><p>Client initiates connection.</p><div class="section" title="A.3.1.1.&nbsp;Client"><div class="titlepage"><div><div><h4 class="title"><a name="d800e70"></a>A.3.1.1.&nbsp;Client</h4></div></div></div><p>On connection setup, client sends a preamble followed by a connection header.
+      </p><div class="section" title="A.3.1.1.1.&nbsp;<preamble&gt;"><div class="titlepage"><div><div><h5 class="title"><a name="d800e75"></a>A.3.1.1.1.&nbsp;&lt;preamble&gt;</h5></div></div></div><pre class="programlisting">&lt;MAGIC 4 byte integer&gt; &lt;1 byte RPC Format Version&gt; &lt;1 byte auth type&gt;<sup>[<a name="d800e81" href="#ftn.d800e81" class="footnote">1</a>]</sup></pre><p>E.g.: HBas0x000x80 -- 4 bytes of MAGIC -- &#8216;HBas&#8217; -- plus one-byte of version, 0 in this case, and one byte, 0x80 (SIMPLE). of an auth type.</p></div><div class="section" title="A.3.1.1.2.&nbsp;<Protobuf ConnectionHeader Message&gt;"><div class="titlepage"><div><div><h5 class="title"><a name="d800e86"></a>A.3.1.1.2.&nbsp;&lt;Protobuf ConnectionHeader Message&gt;</h5></div></div></div><p>Has user info, and &#8220;protocol&#8221;, as well as the encoders and compression the client will use sending CellBlocks.
           CellBlock encoders and compressors are for the life of the connection.
           CellBlock encoders implement org.apache.hadoop.hbase.codec.Codec.
           CellBlocks may then also be compressed.
           Compressors implement org.apache.hadoop.io.compress.CompressionCodec.
           This protobuf is written using writeDelimited so is prefaced by a pb varint
-          with its serialized length</p></div></div><div class="section" title="A.3.1.2.&nbsp;Server"><div class="titlepage"><div><div><h4 class="title"><a name="d746e92"></a>A.3.1.2.&nbsp;Server</h4></div></div></div><p>After client sends preamble and connection header,
+          with its serialized length</p></div></div><div class="section" title="A.3.1.2.&nbsp;Server"><div class="titlepage"><div><div><h4 class="title"><a name="d800e92"></a>A.3.1.2.&nbsp;Server</h4></div></div></div><p>After client sends preamble and connection header,
           server does NOT respond if successful connection setup.
           No response means server is READY to accept requests and to give out response.
       If the version or authentication in the preamble is not agreeable or the server has trouble parsing the preamble,
       it will throw a org.apache.hadoop.hbase.ipc.FatalConnectionException explaining the error and will then disconnect.
       If the client in the connection header -- i.e. the protobuf&#8217;d Message that comes after the connection preamble -- asks for for a
-      Service the server does not support or a codec the server does not have, again we throw a FatalConnectionException with explanation.</p></div></div><div class="section" title="A.3.2.&nbsp;Request"><div class="titlepage"><div><div><h3 class="title"><a name="d746e97"></a>A.3.2.&nbsp;Request</h3></div></div></div><p>After a Connection has been set up, client makes requests.  Server responds.</p><p>A request is made up of a protobuf RequestHeader followed by a protobuf Message parameter.
+      Service the server does not support or a codec the server does not have, again we throw a FatalConnectionException with explanation.</p></div></div><div class="section" title="A.3.2.&nbsp;Request"><div class="titlepage"><div><div><h3 class="title"><a name="d800e97"></a>A.3.2.&nbsp;Request</h3></div></div></div><p>After a Connection has been set up, client makes requests.  Server responds.</p><p>A request is made up of a protobuf RequestHeader followed by a protobuf Message parameter.
           The header includes the method name and optionally, metadata on the optional CellBlock that may be following.
           The parameter type suits the method being invoked: i.e. if we are doing a getRegionInfo request,
           the protobuf Message param will be an instance of GetRegionInfoRequest.
           The response will be a GetRegionInfoResponse.
-          The CellBlock is optionally used ferrying the bulk of the RPC data: i.e Cells/KeyValues.</p><p></p><div class="section" title="A.3.2.1.&nbsp;Request Parts"><div class="titlepage"><div><div><h4 class="title"><a name="d746e105"></a>A.3.2.1.&nbsp;Request Parts</h4></div></div></div><div class="section" title="A.3.2.1.1.&nbsp;<Total Length&gt;"><div class="titlepage"><div><div><h5 class="title"><a name="d746e108"></a>A.3.2.1.1.&nbsp;&lt;Total Length&gt;</h5></div></div></div><p>The request is prefaced by an int that holds the total length of what follows.</p></div><div class="section" title="A.3.2.1.2.&nbsp;<Protobuf RequestHeader Message&gt;"><div class="titlepage"><div><div><h5 class="title"><a name="d746e113"></a>A.3.2.1.2.&nbsp;&lt;Protobuf RequestHeader Message&gt;</h5></div></div></div><p>Will have call.id, trace.id, and method name, etc. including optional Metadata on the Cell block IFF one is following.
-              Data is protobuf&#8217;d inline in this pb Message or optionally comes in the following CellBlock</p></div><div class="section" title="A.3.2.1.3.&nbsp;<Protobuf Param Message&gt;"><div class="titlepage"><div><div><h5 class="title"><a name="d746e118"></a>A.3.2.1.3.&nbsp;&lt;Protobuf Param Message&gt;</h5></div></div></div><p>If the method being invoked is getRegionInfo, if you study the Service descriptor for the client to regionserver protocol,
-              you will find that the request sends a GetRegionInfoRequest protobuf Message param in this position.</p></div><div class="section" title="A.3.2.1.4.&nbsp;<CellBlock&gt;"><div class="titlepage"><div><div><h5 class="title"><a name="d746e123"></a>A.3.2.1.4.&nbsp;&lt;CellBlock&gt;</h5></div></div></div><p>An encoded and optionally compressed Cell block.</p></div></div></div><div class="section" title="A.3.3.&nbsp;Response"><div class="titlepage"><div><div><h3 class="title"><a name="d746e130"></a>A.3.3.&nbsp;Response</h3></div></div></div><p>Same as Request, it is a protobuf ResponseHeader followed by a protobuf Message response where the Message response type suits the method invoked.
-          Bulk of the data may come in a following CellBlock.</p><div class="section" title="A.3.3.1.&nbsp;Response Parts"><div class="titlepage"><div><div><h4 class="title"><a name="d746e135"></a>A.3.3.1.&nbsp;Response Parts</h4></div></div></div><div class="section" title="A.3.3.1.1.&nbsp;<Total Length&gt;"><div class="titlepage"><div><div><h5 class="title"><a name="d746e138"></a>A.3.3.1.1.&nbsp;&lt;Total Length&gt;</h5></div></div></div><p>The response is prefaced by an int that holds the total length of what follows.</p></div><div class="section" title="A.3.3.1.2.&nbsp;<Protobuf ResponseHeader Message&gt;"><div class="titlepage"><div><div><h5 class="title"><a name="d746e143"></a>A.3.3.1.2.&nbsp;&lt;Protobuf ResponseHeader Message&gt;</h5></div></div></div><p>Will have call.id, etc. Will include exception if failed processing. &nbsp;Optionally includes metadata on optional, IFF there is a CellBlock following.</p></div><div class="section" title="A.3.3.1.3.&nbsp;<Protobuf 
 Response Message&gt;"><div class="titlepage"><div><div><h5 class="title"><a name="d746e148"></a>A.3.3.1.3.&nbsp;&lt;Protobuf Response Message&gt;</h5></div></div></div><p>Return or may be nothing if exception. If the method being invoked is getRegionInfo, if you study the Service descriptor for the client to regionserver protocol,
-          you will find that the response sends a GetRegionInfoResponse protobuf Message param in this position.</p></div><div class="section" title="A.3.3.1.4.&nbsp;<CellBlock&gt;"><div class="titlepage"><div><div><h5 class="title"><a name="d746e153"></a>A.3.3.1.4.&nbsp;&lt;CellBlock&gt;</h5></div></div></div><p>An encoded and optionally compressed Cell block.</p></div></div></div><div class="section" title="A.3.4.&nbsp;Exceptions"><div class="titlepage"><div><div><h3 class="title"><a name="d746e160"></a>A.3.4.&nbsp;Exceptions</h3></div></div></div><p>There are two distinct types.
+          The CellBlock is optionally used ferrying the bulk of the RPC data: i.e Cells/KeyValues.</p><p></p><div class="section" title="A.3.2.1.&nbsp;Request Parts"><div class="titlepage"><div><div><h4 class="title"><a name="d800e105"></a>A.3.2.1.&nbsp;Request Parts</h4></div></div></div><div class="section" title="A.3.2.1.1.&nbsp;<Total Length&gt;"><div class="titlepage"><div><div><h5 class="title"><a name="d800e108"></a>A.3.2.1.1.&nbsp;&lt;Total Length&gt;</h5></div></div></div><p>The request is prefaced by an int that holds the total length of what follows.</p></div><div class="section" title="A.3.2.1.2.&nbsp;<Protobuf RequestHeader Message&gt;"><div class="titlepage"><div><div><h5 class="title"><a name="d800e113"></a>A.3.2.1.2.&nbsp;&lt;Protobuf RequestHeader Message&gt;</h5></div></div></div><p>Will have call.id, trace.id, and method name, etc. including optional Metadata on the Cell block IFF one is following.
+              Data is protobuf&#8217;d inline in this pb Message or optionally comes in the following CellBlock</p></div><div class="section" title="A.3.2.1.3.&nbsp;<Protobuf Param Message&gt;"><div class="titlepage"><div><div><h5 class="title"><a name="d800e118"></a>A.3.2.1.3.&nbsp;&lt;Protobuf Param Message&gt;</h5></div></div></div><p>If the method being invoked is getRegionInfo, if you study the Service descriptor for the client to regionserver protocol,
+              you will find that the request sends a GetRegionInfoRequest protobuf Message param in this position.</p></div><div class="section" title="A.3.2.1.4.&nbsp;<CellBlock&gt;"><div class="titlepage"><div><div><h5 class="title"><a name="d800e123"></a>A.3.2.1.4.&nbsp;&lt;CellBlock&gt;</h5></div></div></div><p>An encoded and optionally compressed Cell block.</p></div></div></div><div class="section" title="A.3.3.&nbsp;Response"><div class="titlepage"><div><div><h3 class="title"><a name="d800e130"></a>A.3.3.&nbsp;Response</h3></div></div></div><p>Same as Request, it is a protobuf ResponseHeader followed by a protobuf Message response where the Message response type suits the method invoked.
+          Bulk of the data may come in a following CellBlock.</p><div class="section" title="A.3.3.1.&nbsp;Response Parts"><div class="titlepage"><div><div><h4 class="title"><a name="d800e135"></a>A.3.3.1.&nbsp;Response Parts</h4></div></div></div><div class="section" title="A.3.3.1.1.&nbsp;<Total Length&gt;"><div class="titlepage"><div><div><h5 class="title"><a name="d800e138"></a>A.3.3.1.1.&nbsp;&lt;Total Length&gt;</h5></div></div></div><p>The response is prefaced by an int that holds the total length of what follows.</p></div><div class="section" title="A.3.3.1.2.&nbsp;<Protobuf ResponseHeader Message&gt;"><div class="titlepage"><div><div><h5 class="title"><a name="d800e143"></a>A.3.3.1.2.&nbsp;&lt;Protobuf ResponseHeader Message&gt;</h5></div></div></div><p>Will have call.id, etc. Will include exception if failed processing. &nbsp;Optionally includes metadata on optional, IFF there is a CellBlock following.</p></div><div class="section" title="A.3.3.1.3.&nbsp;<Protobuf 
 Response Message&gt;"><div class="titlepage"><div><div><h5 class="title"><a name="d800e148"></a>A.3.3.1.3.&nbsp;&lt;Protobuf Response Message&gt;</h5></div></div></div><p>Return or may be nothing if exception. If the method being invoked is getRegionInfo, if you study the Service descriptor for the client to regionserver protocol,
+          you will find that the response sends a GetRegionInfoResponse protobuf Message param in this position.</p></div><div class="section" title="A.3.3.1.4.&nbsp;<CellBlock&gt;"><div class="titlepage"><div><div><h5 class="title"><a name="d800e153"></a>A.3.3.1.4.&nbsp;&lt;CellBlock&gt;</h5></div></div></div><p>An encoded and optionally compressed Cell block.</p></div></div></div><div class="section" title="A.3.4.&nbsp;Exceptions"><div class="titlepage"><div><div><h3 class="title"><a name="d800e160"></a>A.3.4.&nbsp;Exceptions</h3></div></div></div><p>There are two distinct types.
           There is the request failed which is encapsulated inside the response header for the response.
           The connection stays open to receive new requests.
           The second type, the FatalConnectionException, kills the connection.</p><p>Exceptions can carry extra information.
           See the ExceptionResponse protobuf type.
-          It has a flag to indicate do-no-retry as well as other miscellaneous payload to help improve client responsiveness.</p></div><div class="section" title="A.3.5.&nbsp;CellBlocks"><div class="titlepage"><div><div><h3 class="title"><a name="d746e167"></a>A.3.5.&nbsp;CellBlocks</h3></div></div></div><p>These are not versioned.
+          It has a flag to indicate do-no-retry as well as other miscellaneous payload to help improve client responsiveness.</p></div><div class="section" title="A.3.5.&nbsp;CellBlocks"><div class="titlepage"><div><div><h3 class="title"><a name="d800e167"></a>A.3.5.&nbsp;CellBlocks</h3></div></div></div><p>These are not versioned.
           Server can do the codec or it cannot.
           If new version of a codec with say, tighter encoding, then give it a new class name.
-          Codecs will live on the server for all time so old clients can connect.</p></div><div class="footnotes"><br><hr width="100" align="left"><div class="footnote"><p><sup>[<a id="ftn.d746e81" href="#d746e81" class="para">1</a>] </sup> We need the auth method spec. here so the connection header is encoded if auth enabled.</p></div></div></div><div id="disqus_thread"></div><script type="text/javascript">
+          Codecs will live on the server for all time so old clients can connect.</p></div><div class="footnotes"><br><hr width="100" align="left"><div class="footnote"><p><sup>[<a id="ftn.d800e81" href="#d800e81" class="para">1</a>] </sup> We need the auth method spec. here so the connection header is encoded if auth enabled.</p></div></div></div><div id="disqus_thread"></div><script type="text/javascript">
     var disqus_shortname = 'hbase'; // required: replace example with your forum shortname
     var disqus_url = 'http://hbase.apache.org/book';
     var disqus_identifier = '';

Modified: hbase/hbase.apache.org/trunk/rpc/apas04.html
URL: http://svn.apache.org/viewvc/hbase/hbase.apache.org/trunk/rpc/apas04.html?rev=1465200&r1=1465199&r2=1465200&view=diff
==============================================================================
--- hbase/hbase.apache.org/trunk/rpc/apas04.html (original)
+++ hbase/hbase.apache.org/trunk/rpc/apas04.html Sat Apr  6 06:08:56 2013
@@ -1,9 +1,9 @@
 <html><head>
       <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
-   <title>A.4.&nbsp;Notes</title><link rel="stylesheet" type="text/css" href="../css/freebsd_docbook.css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.76.1"><link rel="home" href="rpc.html" title="Appendix&nbsp;A.&nbsp;0.95 RPC Specification"><link rel="up" href="rpc.html" title="Appendix&nbsp;A.&nbsp;0.95 RPC Specification"><link rel="prev" href="apas03.html" title="A.3.&nbsp;RPC"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">A.4.&nbsp;Notes</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="apas03.html">Prev</a>&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;</td></tr></table><hr></div><div class="section" title="A.4.&nbsp;Notes"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d746e172"></a>A.4.&nbsp;Notes</h2></div></div></
 div><div class="section" title="A.4.1.&nbsp;Constraints"><div class="titlepage"><div><div><h3 class="title"><a name="d746e175"></a>A.4.1.&nbsp;Constraints</h3></div></div></div><p>In some part, current wire-format -- i.e. all requests and responses preceeded by a length -- has been dictated by current server non-async architecture.</p></div><div class="section" title="A.4.2.&nbsp;One fat pb request or header+param"><div class="titlepage"><div><div><h3 class="title"><a name="d746e180"></a>A.4.2.&nbsp;One fat pb request or header+param</h3></div></div></div><p>We went with pb header followed by pb param making a request and a pb header followed by pb response for now.
+   <title>A.4.&nbsp;Notes</title><link rel="stylesheet" type="text/css" href="../css/freebsd_docbook.css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.76.1"><link rel="home" href="rpc.html" title="Appendix&nbsp;A.&nbsp;0.95 RPC Specification"><link rel="up" href="rpc.html" title="Appendix&nbsp;A.&nbsp;0.95 RPC Specification"><link rel="prev" href="apas03.html" title="A.3.&nbsp;RPC"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">A.4.&nbsp;Notes</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="apas03.html">Prev</a>&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;</td></tr></table><hr></div><div class="section" title="A.4.&nbsp;Notes"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d800e172"></a>A.4.&nbsp;Notes</h2></div></div></
 div><div class="section" title="A.4.1.&nbsp;Constraints"><div class="titlepage"><div><div><h3 class="title"><a name="d800e175"></a>A.4.1.&nbsp;Constraints</h3></div></div></div><p>In some part, current wire-format -- i.e. all requests and responses preceeded by a length -- has been dictated by current server non-async architecture.</p></div><div class="section" title="A.4.2.&nbsp;One fat pb request or header+param"><div class="titlepage"><div><div><h3 class="title"><a name="d800e180"></a>A.4.2.&nbsp;One fat pb request or header+param</h3></div></div></div><p>We went with pb header followed by pb param making a request and a pb header followed by pb response for now.
           Doing header+param rather than a single protobuf Message with both header and param content:</p><p>
   </p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem"><p>Is closer to what we currently have</p></li><li class="listitem"><p>Having a single fat pb requires extra copying putting the already pb&#8217;d param into the body of the fat request pb (and same making result)</p></li><li class="listitem"><p>We can decide whether to accept the request or not before we read the param; for example, the request might be low priority. &nbsp;As is, we read header+param in one go as server is currently implemented so this is a TODO.</p></li></ol></div><p>
-  </p><p>The advantages are minor. &nbsp;If later, fat request has clear advantage, can roll out a v2 later.</p></div><div class="section" title="A.4.3.&nbsp;Compression"><div class="titlepage"><div><div><h3 class="title"><a name="d746e200"></a>A.4.3.&nbsp;Compression</h3></div></div></div><p>Uses hadoops compression codecs.</p></div></div><div id="disqus_thread"></div><script type="text/javascript">
+  </p><p>The advantages are minor. &nbsp;If later, fat request has clear advantage, can roll out a v2 later.</p></div><div class="section" title="A.4.3.&nbsp;Compression"><div class="titlepage"><div><div><h3 class="title"><a name="d800e200"></a>A.4.3.&nbsp;Compression</h3></div></div></div><p>Uses hadoops compression codecs.</p></div></div><div id="disqus_thread"></div><script type="text/javascript">
     var disqus_shortname = 'hbase'; // required: replace example with your forum shortname
     var disqus_url = 'http://hbase.apache.org/book';
     var disqus_identifier = '';

Modified: hbase/hbase.apache.org/trunk/rpc/rpc.html
URL: http://svn.apache.org/viewvc/hbase/hbase.apache.org/trunk/rpc/rpc.html?rev=1465200&r1=1465199&r2=1465200&view=diff
==============================================================================
--- hbase/hbase.apache.org/trunk/rpc/rpc.html (original)
+++ hbase/hbase.apache.org/trunk/rpc/rpc.html Sat Apr  6 06:08:56 2013
@@ -1,13 +1,13 @@
 <html><head>
       <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
-   <title>Appendix&nbsp;A.&nbsp;0.95 RPC Specification</title><link rel="stylesheet" type="text/css" href="../css/freebsd_docbook.css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.76.1"><link rel="home" href="rpc.html" title="Appendix&nbsp;A.&nbsp;0.95 RPC Specification"><link rel="next" href="apas02.html" title="A.2.&nbsp;TODO"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Appendix&nbsp;A.&nbsp;0.95 RPC Specification</th></tr><tr><td width="20%" align="left">&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;<a accesskey="n" href="apas02.html">Next</a></td></tr></table><hr></div><div class="appendix" title="Appendix&nbsp;A.&nbsp;0.95 RPC Specification"><div class="titlepage"><div><div><h2 class="title"><a name="hbase.rpc"></a>Appendix&nbsp;A.&nbsp;0.95 RPC Specification</h2
 ></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="section"><a href="rpc.html#d746e22">A.1. Goals</a></span></dt><dt><span class="section"><a href="apas02.html">A.2. TODO</a></span></dt><dt><span class="section"><a href="apas03.html">A.3. RPC</a></span></dt><dd><dl><dt><span class="section"><a href="apas03.html#d746e65">A.3.1. Connection Setup</a></span></dt><dt><span class="section"><a href="apas03.html#d746e97">A.3.2. Request</a></span></dt><dt><span class="section"><a href="apas03.html#d746e130">A.3.3. Response</a></span></dt><dt><span class="section"><a href="apas03.html#d746e160">A.3.4. Exceptions</a></span></dt><dt><span class="section"><a href="apas03.html#d746e167">A.3.5. CellBlocks</a></span></dt></dl></dd><dt><span class="section"><a href="apas04.html">A.4. Notes</a></span></dt><dd><dl><dt><span class="section"><a href="apas04.html#d746e175">A.4.1. Constraints</a></span></dt><dt><span class="section"><a href="apas04.html#d746e18
 0">A.4.2. One fat pb request or header+param</a></span></dt><dt><span class="section"><a href="apas04.html#d746e200">A.4.3. Compression</a></span></dt></dl></dd></dl></div><p>In 0.95, all client/server communication is done with
+   <title>Appendix&nbsp;A.&nbsp;0.95 RPC Specification</title><link rel="stylesheet" type="text/css" href="../css/freebsd_docbook.css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.76.1"><link rel="home" href="rpc.html" title="Appendix&nbsp;A.&nbsp;0.95 RPC Specification"><link rel="next" href="apas02.html" title="A.2.&nbsp;TODO"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Appendix&nbsp;A.&nbsp;0.95 RPC Specification</th></tr><tr><td width="20%" align="left">&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;<a accesskey="n" href="apas02.html">Next</a></td></tr></table><hr></div><div class="appendix" title="Appendix&nbsp;A.&nbsp;0.95 RPC Specification"><div class="titlepage"><div><div><h2 class="title"><a name="hbase.rpc"></a>Appendix&nbsp;A.&nbsp;0.95 RPC Specification</h2
 ></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="section"><a href="rpc.html#d800e22">A.1. Goals</a></span></dt><dt><span class="section"><a href="apas02.html">A.2. TODO</a></span></dt><dt><span class="section"><a href="apas03.html">A.3. RPC</a></span></dt><dd><dl><dt><span class="section"><a href="apas03.html#d800e65">A.3.1. Connection Setup</a></span></dt><dt><span class="section"><a href="apas03.html#d800e97">A.3.2. Request</a></span></dt><dt><span class="section"><a href="apas03.html#d800e130">A.3.3. Response</a></span></dt><dt><span class="section"><a href="apas03.html#d800e160">A.3.4. Exceptions</a></span></dt><dt><span class="section"><a href="apas03.html#d800e167">A.3.5. CellBlocks</a></span></dt></dl></dd><dt><span class="section"><a href="apas04.html">A.4. Notes</a></span></dt><dd><dl><dt><span class="section"><a href="apas04.html#d800e175">A.4.1. Constraints</a></span></dt><dt><span class="section"><a href="apas04.html#d800e18
 0">A.4.2. One fat pb request or header+param</a></span></dt><dt><span class="section"><a href="apas04.html#d800e200">A.4.3. Compression</a></span></dt></dl></dd></dl></div><p>In 0.95, all client/server communication is done with
       <a class="link" href="https://code.google.com/p/protobuf/" target="_top">protobuf&#8217;ed</a> Messages rather than with
       <a class="link" href="http://hadoop.apache.org/docs/current/api/org/apache/hadoop/io/Writable.html" target="_top">Hadoop Writables</a>.
       Our RPC wire format therefore changes.
       This document describes the client/server request/response protocol and our new RPC wire-format.</p><p></p><p>For what RPC is like in 0.94 and previous,
       see Beno&icirc;t/Tsuna&#8217;s <a class="link" href="https://github.com/OpenTSDB/asynchbase/blob/master/src/HBaseRpc.java#L164" target="_top">Unofficial Hadoop / HBase RPC protocol documentation</a>.
       For more background on how we arrived at this spec., see
-      <a class="link" href="https://docs.google.com/document/d/1WCKwgaLDqBw2vpux0jPsAu2WPTRISob7HGCO8YhfDTA/edit#" target="_top">HBase RPC: WIP</a></p><p></p><div class="section" title="A.1.&nbsp;Goals"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d746e22"></a>A.1.&nbsp;Goals</h2></div></div></div><p>
+      <a class="link" href="https://docs.google.com/document/d/1WCKwgaLDqBw2vpux0jPsAu2WPTRISob7HGCO8YhfDTA/edit#" target="_top">HBase RPC: WIP</a></p><p></p><div class="section" title="A.1.&nbsp;Goals"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d800e22"></a>A.1.&nbsp;Goals</h2></div></div></div><p>
       </p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem"><p>A wire-format we can evolve</p></li><li class="listitem"><p>A format that does not require our rewriting server core or
                   radically changing its current architecture (for later).</p></li></ol></div><p>
   </p></div></div><div id="disqus_thread"></div><script type="text/javascript">

Modified: hbase/hbase.apache.org/trunk/schema_design.html
URL: http://svn.apache.org/viewvc/hbase/hbase.apache.org/trunk/schema_design.html?rev=1465200&r1=1465199&r2=1465200&view=diff
==============================================================================
--- hbase/hbase.apache.org/trunk/schema_design.html (original)
+++ hbase/hbase.apache.org/trunk/schema_design.html Sat Apr  6 06:08:56 2013
@@ -26,7 +26,7 @@
        Summary Tables
       </a></span></dt><dt><span class="section"><a href="#secondary.indexes.coproc">1.9.5. 
        Coprocessor Secondary Index
-      </a></span></dt></dl></dd><dt><span class="section"><a href="#constraints">1.10. Constraints</a></span></dt><dt><span class="section"><a href="#schema.casestudies">1.11. Schema Design Case Studies</a></span></dt><dd><dl><dt><span class="section"><a href="#schema.casestudies.log-timeseries">1.11.1. Log Data and Timeseries Data Case Study</a></span></dt><dt><span class="section"><a href="#schema.casestudies.log-timeseries.log-steroids">1.11.2. Log Data and Timeseries Data on Steroids Case Study</a></span></dt><dt><span class="section"><a href="#schema.casestudies.log-timeseries.custsales">1.11.3. Customer / Sales Case Study</a></span></dt><dt><span class="section"><a href="#schema.smackdown">1.11.4. "Tall/Wide/Middle" Schema Design Smackdown</a></span></dt></dl></dd><dt><span class="section"><a href="#schema.ops">1.12. Operational and Performance Configuration Options</a></span></dt></dl></div><p>A good general introduction on the strength and weaknesses modelling on
+      </a></span></dt></dl></dd><dt><span class="section"><a href="#constraints">1.10. Constraints</a></span></dt><dt><span class="section"><a href="#schema.casestudies">1.11. Schema Design Case Studies</a></span></dt><dd><dl><dt><span class="section"><a href="#schema.casestudies.log-timeseries">1.11.1. Case Study - Log Data and Timeseries Data</a></span></dt><dt><span class="section"><a href="#schema.casestudies.log-steroids">1.11.2. Case Study - Log Data and Timeseries Data on Steroids</a></span></dt><dt><span class="section"><a href="#schema.casestudies.custorder">1.11.3. Case Study - Customer/Order</a></span></dt><dt><span class="section"><a href="#schema.smackdown">1.11.4. Case Study - "Tall/Wide/Middle" Schema Design Smackdown</a></span></dt><dt><span class="section"><a href="#casestudies.schema.listdata">1.11.5. Case Study - List Data</a></span></dt></dl></dd><dt><span class="section"><a href="#schema.ops">1.12. Operational and Performance Configuration Options</a></s
 pan></dt></dl></div><p>A good general introduction on the strength and weaknesses modelling on
           the various non-rdbms datastores is Ian Varley's Master thesis,
           <a class="link" href="http://ianvarley.com/UT/MR/Varley_MastersReport_Full_2009-08-07.pdf" target="_top">No Relation: The Mixed Blessings of Non-Relational Databases</a>.
           Recommended.  Also, read <a class="xref" href="#">???</a> for how HBase stores data internally, and the section on 
@@ -288,10 +288,11 @@ public static byte[][] getHexSplits(Stri
     </p></div><div class="section" title="1.11.&nbsp;Schema Design Case Studies"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="schema.casestudies"></a>1.11.&nbsp;Schema Design Case Studies</h2></div></div></div><p>The following will describe some typical data ingestion use-cases with HBase, and how the rowkey design and construction
    can be approached.  Note:  this is just an illustration of potential approaches, not an exhaustive list. 
    Know your data, and know your processing requirements.
-  </p><p>There are 3 case studies described:    
-      </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem">Log Data / Timeseries Data</li><li class="listitem">Log Data / Timeseries on Steroids</li><li class="listitem">Customer/Sales</li></ul></div><p> 
-    ... and then a brief section on "Tall/Wide/Middle" in terms of schema design approaches.
-  </p><div class="section" title="1.11.1.&nbsp;Log Data and Timeseries Data Case Study"><div class="titlepage"><div><div><h3 class="title"><a name="schema.casestudies.log-timeseries"></a>1.11.1.&nbsp;Log Data and Timeseries Data Case Study</h3></div></div></div><p>Assume that the following data elements are being collected.
+  </p><p>It is highly recommended that you read the rest of the <a class="xref" href="#schema" title="Chapter&nbsp;1.&nbsp;HBase and Schema Design">Chapter&nbsp;1, <i>HBase and Schema Design</i></a> first, before reading
+  these case studies.
+  </p><p>Thee following case studies are described:    
+      </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem">Log Data / Timeseries Data</li><li class="listitem">Log Data / Timeseries on Steroids</li><li class="listitem">Customer/Order</li><li class="listitem">Tall/Wide/Middle Schema Design</li><li class="listitem">List Data</li></ul></div><p> 
+  </p><div class="section" title="1.11.1.&nbsp;Case Study - Log Data and Timeseries Data"><div class="titlepage"><div><div><h3 class="title"><a name="schema.casestudies.log-timeseries"></a>1.11.1.&nbsp;Case Study - Log Data and Timeseries Data</h3></div></div></div><p>Assume that the following data elements are being collected.
         </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem">Hostname</li><li class="listitem">Timestamp</li><li class="listitem">Log event</li><li class="listitem">Value/message</li></ul></div><p>
         We can store them in an HBase table called LOG_DATA, but what will the rowkey be?  
        From these attributes the rowkey will be some combination of hostname, timestamp, and log-event - but what specifically?        
@@ -334,8 +335,10 @@ long bucket = timestamp % numBuckets;
         </p><p>So the resulting composite rowkey would be:
 		</p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem">[substituted long for hostname] = 8 bytes</li><li class="listitem">[substituted long for event type] = 8 bytes</li><li class="listitem">[timestamp] = 8 bytes</li></ul></div><p>
 		In either the Hash or Numeric substitution approach, the raw values for hostname and event-type can be stored as columns.
-        </p></div></div><div class="section" title="1.11.2.&nbsp;Log Data and Timeseries Data on Steroids Case Study"><div class="titlepage"><div><div><h3 class="title"><a name="schema.casestudies.log-timeseries.log-steroids"></a>1.11.2.&nbsp;Log Data and Timeseries Data on Steroids Case Study</h3></div></div></div><p>This effectively is the OpenTSDB approach.  What OpenTSDB does is re-write data and pack rows into columns for 
-        certain time-periods.  For a detailed explanation, see:  <a class="link" href="http://opentsdb.net/schema.html" target="_top">http://opentsdb.net/schema.html</a>.
+        </p></div></div><div class="section" title="1.11.2.&nbsp;Case Study - Log Data and Timeseries Data on Steroids"><div class="titlepage"><div><div><h3 class="title"><a name="schema.casestudies.log-steroids"></a>1.11.2.&nbsp;Case Study - Log Data and Timeseries Data on Steroids</h3></div></div></div><p>This effectively is the OpenTSDB approach.  What OpenTSDB does is re-write data and pack rows into columns for 
+        certain time-periods.  For a detailed explanation, see:  <a class="link" href="http://opentsdb.net/schema.html" target="_top">http://opentsdb.net/schema.html</a>, 
+        and <a class="link" href="http://www.cloudera.com/content/cloudera/en/resources/library/hbasecon/video-hbasecon-2012-lessons-learned-from-opentsdb.html" target="_top">Lessons Learned from OpenTSDB</a>
+	    from HBaseCon2012.
       </p><p>But this is how the general concept works:  data is ingested, for example, in this manner&#8230;
 </p><pre class="programlisting">
 [hostname][log-event][timestamp1]
@@ -346,34 +349,79 @@ long bucket = timestamp % numBuckets;
        </p><p><code class="code">[hostname][log-event][timerange]</code>
        </p><p>&#8230; and each of the above events are converted into columns stored with a time-offset relative to the beginning timerange 
        (e.g., every 5 minutes).  This is obviously a very advanced processing technique, but HBase makes this possible.
-      </p></div><div class="section" title="1.11.3.&nbsp;Customer / Sales Case Study"><div class="titlepage"><div><div><h3 class="title"><a name="schema.casestudies.log-timeseries.custsales"></a>1.11.3.&nbsp;Customer / Sales Case Study</h3></div></div></div><p>Assume that HBase is used to store customer and sales information.  There are two core record-types being ingested:  
-        a Customer record type, and Sales record type.
+      </p></div><div class="section" title="1.11.3.&nbsp;Case Study - Customer/Order"><div class="titlepage"><div><div><h3 class="title"><a name="schema.casestudies.custorder"></a>1.11.3.&nbsp;Case Study - Customer/Order</h3></div></div></div><p>Assume that HBase is used to store customer and order information.  There are two core record-types being ingested:  
+        a Customer record type, and Order record type.
       </p><p>The Customer record type would include all the things that you&#8217;d typically expect:
         </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem">Customer number</li><li class="listitem">Customer name</li><li class="listitem">Address (e.g., city, state, zip)</li><li class="listitem">Phone numbers, etc.</li></ul></div><p>
-     </p><p>The Sales record type would include things like:
-        </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem">Customer number</li><li class="listitem">Sales/order number</li><li class="listitem">Sales date</li><li class="listitem">A series of nested objects for shipping locations and line-items (this itself is a design case study)</li></ul></div><p>
+     </p><p>The Order record type would include things like:
+        </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem">Customer number</li><li class="listitem">Order number</li><li class="listitem">Sales date</li><li class="listitem">A series of nested objects for shipping locations and line-items (see <a class="xref" href="#schema.casestudies.custorder.obj" title="1.11.3.2.&nbsp;Order Object Design">Section&nbsp;1.11.3.2, &#8220;Order Object Design&#8221;</a>
+           for details)</li></ul></div><p>
     </p><p>Assuming that the combination of customer number and sales order uniquely identify an order, these two attributes will compose
  the rowkey, and specifically a composite key such as:
-    </p><p><code class="code">[customer number][sales number]</code>
-    </p><p>
-&#8230; for a SALES table.  However, there are more design decisions to make:  are the <span class="emphasis"><em>raw</em></span> values the best choices for rowkeys?
+    </p><p><code class="code">[customer number][order number]</code>
+    </p><p>&#8230; for a ORDER table.  However, there are more design decisions to make:  are the <span class="emphasis"><em>raw</em></span> values the best choices for rowkeys?
     </p><p>The same design questions in the Log Data use-case confront us here.  What is the keyspace of the customer number, and what is the 
 format (e.g., numeric?  alphanumeric?) As it is advantageous to use fixed-length keys in HBase, as well as keys that can support a 
 reasonable spread in the keyspace, similar options appear:
     </p><p>Composite Rowkey With Hashes:  
-      </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem">[MD5 of customer number] = 16 bytes</li><li class="listitem">[MD5 of sales number] = 16 bytes</li></ul></div><p>
+      </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem">[MD5 of customer number] = 16 bytes</li><li class="listitem">[MD5 of order number] = 16 bytes</li></ul></div><p>
     </p><p>Composite Numeric/Hash Combo Rowkey: 
-      </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem">[substituted long for customer number] = 8 bytes</li><li class="listitem">[MD5 of sales number] = 16 bytes</li></ul></div><p>
-     </p><div class="section" title="1.11.3.1.&nbsp;Single Table? Multiple Tables?"><div class="titlepage"><div><div><h4 class="title"><a name="schema.casestudies.log-timeseries.custsales.tables"></a>1.11.3.1.&nbsp;Single Table?  Multiple Tables?</h4></div></div></div><p>A traditional design approach would have separate tables for CUSTOMER and SALES.  Another option is to pack multiple 
+      </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem">[substituted long for customer number] = 8 bytes</li><li class="listitem">[MD5 of order number] = 16 bytes</li></ul></div><p>
+     </p><div class="section" title="1.11.3.1.&nbsp;Single Table? Multiple Tables?"><div class="titlepage"><div><div><h4 class="title"><a name="schema.casestudies.custorder.tables"></a>1.11.3.1.&nbsp;Single Table?  Multiple Tables?</h4></div></div></div><p>A traditional design approach would have separate tables for CUSTOMER and SALES.  Another option is to pack multiple 
             record types into a single table (e.g., CUSTOMER++).            
             </p><p>Customer Record Type Rowkey:
               </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem">[customer-id]</li><li class="listitem">[type] = type indicating &#8216;1&#8217; for customer record type</li></ul></div><p>
-            </p><p>Sales Record Type Rowkey:
-              </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem">[customer-id]</li><li class="listitem">[type] = type indicating &#8216;2&#8217; for sales record type</li><li class="listitem">[sales-order]</li></ul></div><p>
+            </p><p>Order Record Type Rowkey:
+              </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem">[customer-id]</li><li class="listitem">[type] = type indicating &#8216;2&#8217; for order record type</li><li class="listitem">[order]</li></ul></div><p>
             </p><p>The advantage of this particular CUSTOMER++ approach is that organizes many different record-types by customer-id 
             (e.g., a single scan could get you everything about that customer).  The disadvantage is that it&#8217;s not as easy to scan for
             a particular record-type.
-            </p></div></div><div class="section" title="1.11.4.&nbsp;&#34;Tall/Wide/Middle&#34; Schema Design Smackdown"><div class="titlepage"><div><div><h3 class="title"><a name="schema.smackdown"></a>1.11.4.&nbsp;"Tall/Wide/Middle" Schema Design Smackdown</h3></div></div></div><p>This section will describe additional schema design questions that appear on the dist-list, specifically about
+            </p></div><div class="section" title="1.11.3.2.&nbsp;Order Object Design"><div class="titlepage"><div><div><h4 class="title"><a name="schema.casestudies.custorder.obj"></a>1.11.3.2.&nbsp;Order Object Design</h4></div></div></div><p>Now we need to address how to model the Order object.  Assume that the class structure is as follows:
+</p><pre class="programlisting">
+<code class="filename">Order</code>
+     <code class="filename">ShippingLocation</code>     (an Order can have multiple ShippingLocations)
+          <code class="filename">LineItem</code>               (a ShippingLocation can have multiple LineItems)
+</pre><p>
+	       ... there are multiple options on storing this data.
+	      </p><div class="section" title="1.11.3.2.1.&nbsp;Completely Normalized"><div class="titlepage"><div><div><h5 class="title"><a name="schema.casestudies.custorder.obj.norm"></a>1.11.3.2.1.&nbsp;Completely Normalized</h5></div></div></div><p>With this approach, there would be separate tables for ORDER, SHIPPING_LOCATION, and LINE_ITEM.          
+	        </p><p>The ORDER table's rowkey was described above: <a class="xref" href="#schema.casestudies.custorder" title="1.11.3.&nbsp;Case Study - Customer/Order">Section&nbsp;1.11.3, &#8220;Case Study - Customer/Order&#8221;</a>
+	        </p><p>The SHIPPING_LOCATION's composite rowkey would be something like this:
+	          </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem">[order-rowkey]</li><li class="listitem">[shipping location number] (e.g., 1st location, 2nd, etc.)</li></ul></div><p>
+	        </p><p>The LINE_ITEM table's composite rowkey would be something like this:
+	          </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem">[order-rowkey]</li><li class="listitem">[shipping location number] (e.g., 1st location, 2nd, etc.)</li><li class="listitem">[line item number] (e.g., 1st lineitem, 2nd, etc.)</li></ul></div><p>
+	        </p><p>Such a normalized model is likely to be the approach with an RDBMS, but that's not your only option with HBase.
+	        The cons of such an approach is that to retrieve information about any Order, you will need:
+	          </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem">Get on the ORDER table for the Order</li><li class="listitem">Scan on the SHIPPING_LOCATION table for that order to get the ShippingLocation instances</li><li class="listitem">Scan on the LINE_ITEM for each ShippingLocation</li></ul></div><p>
+	          ... granted, this is what an RDBMS would do under the covers anyway, but since there are no joins in HBase
+	          you're just more aware of this fact.
+	        </p></div><div class="section" title="1.11.3.2.2.&nbsp;Single Table With Record Types"><div class="titlepage"><div><div><h5 class="title"><a name="schema.casestudies.custorder.obj.rectype"></a>1.11.3.2.2.&nbsp;Single Table With Record Types</h5></div></div></div><p>With this approach, there would exist a single table ORDER that would contain 
+	        </p><p>The Order rowkey was described above: <a class="xref" href="#schema.casestudies.custorder" title="1.11.3.&nbsp;Case Study - Customer/Order">Section&nbsp;1.11.3, &#8220;Case Study - Customer/Order&#8221;</a>
+	          </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem">[order-rowkey]</li><li class="listitem">[ORDER record type]</li></ul></div><p>
+	        </p><p>The ShippingLocation composite rowkey would be something like this:
+	          </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem">[order-rowkey]</li><li class="listitem">[SHIPPING record type]</li><li class="listitem">[shipping location number] (e.g., 1st location, 2nd, etc.)</li></ul></div><p>
+	        </p><p>The LineItem composite rowkey would be something like this:
+	          </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem">[order-rowkey]</li><li class="listitem">[LINE record type]</li><li class="listitem">[shipping location number] (e.g., 1st location, 2nd, etc.)</li><li class="listitem">[line item number] (e.g., 1st lineitem, 2nd, etc.)</li></ul></div><p>
+	        </p></div><div class="section" title="1.11.3.2.3.&nbsp;Denormalized"><div class="titlepage"><div><div><h5 class="title"><a name="schema.casestudies.custorder.obj.denorm"></a>1.11.3.2.3.&nbsp;Denormalized</h5></div></div></div><p>A variant of the Single Table With Record Types approach is to denormalize and flatten some of the object 
+	        hierarchy, such as collapsing the ShippingLocation attributes onto each LineItem instance.
+	        </p><p>The LineItem composite rowkey would be something like this:
+	          </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem">[order-rowkey]</li><li class="listitem">[LINE record type]</li><li class="listitem">[line item number] (e.g., 1st lineitem, 2nd, etc. - care must be taken that there are unique across the entire order)</li></ul></div><p>
+	        </p><p>... and the LineItem columns would be something like this:
+	          </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem">itemNumber</li><li class="listitem">quantity</li><li class="listitem">price</li><li class="listitem">shipToLine1 (denormalized from ShippingLocation)</li><li class="listitem">shipToLine2 (denormalized from ShippingLocation)</li><li class="listitem">shipToCity (denormalized from ShippingLocation)</li><li class="listitem">shipToState (denormalized from ShippingLocation)</li><li class="listitem">shipToZip (denormalized from ShippingLocation)</li></ul></div><p>
+	        </p><p>The pros of this approach include a less complex object heirarchy, but one of the cons is that updating gets more 
+	        complicated in case any of this information changes.
+	        </p></div><div class="section" title="1.11.3.2.4.&nbsp;Object BLOB"><div class="titlepage"><div><div><h5 class="title"><a name="schema.casestudies.custorder.obj.singleobj"></a>1.11.3.2.4.&nbsp;Object BLOB</h5></div></div></div><p>With this approach, the entire Order object graph is treated, in one way or another, as a BLOB.  For example, the 
+	        ORDER table's rowkey was described above: <a class="xref" href="#schema.casestudies.custorder" title="1.11.3.&nbsp;Case Study - Customer/Order">Section&nbsp;1.11.3, &#8220;Case Study - Customer/Order&#8221;</a>, and a 
+	        single column called "order" would contain an object that could be deserialized that contained a container Order, 
+	        ShippingLocations, and LineItems.
+	        </p><p>There are many options here:  JSON, XML, Java Serialization, Avro, Hadoop Writables, etc.  All of them are variants
+	        of the same approach:  encode the object graph to a byte-array.  Care should be taken with this approach to ensure backward 
+	        compatibilty in case the object model changes such that older persisted structures can still be read back out of HBase.
+	        </p><p>Pros are being able to manage complex object graphs with minimal I/O (e.g., a single HBase Get per
+	        Order in this example), but the cons include the aforementioned warning about backward compatiblity of serialization,
+	        language dependencies of serialization (e.g., Java Serialization only works with Java clients), the fact that
+	        you have to deserialize the entire object to get any piece of information inside the BLOB, and the difficulty in 
+	        getting frameworks like Hive to work with custom objects like this.
+	        </p></div></div></div><div class="section" title="1.11.4.&nbsp;Case Study - &#34;Tall/Wide/Middle&#34; Schema Design Smackdown"><div class="titlepage"><div><div><h3 class="title"><a name="schema.smackdown"></a>1.11.4.&nbsp;Case Study - "Tall/Wide/Middle" Schema Design Smackdown</h3></div></div></div><p>This section will describe additional schema design questions that appear on the dist-list, specifically about
 	  tall and wide tables.  These are general guidelines and not laws - each application must consider its own needs.
 	  </p><div class="section" title="1.11.4.1.&nbsp;Rows vs. Versions"><div class="titlepage"><div><div><h4 class="title"><a name="schema.smackdown.rowsversions"></a>1.11.4.1.&nbsp;Rows vs. Versions</h4></div></div></div><p>A common question is whether one should prefer rows or HBase's built-in-versioning.  The context is typically where there are
 	    "a lot" of versions of a row to be retained (e.g., where it is significantly above the HBase default of 3 max versions).  The
@@ -388,9 +436,116 @@ reasonable spread in the keyspace, simil
 	    OpenTSDB is the best example of this case where a single row represents a defined time-range, and then discrete events are treated as
 	    columns.  This approach is often more complex, and may require the additional complexity of re-writing your data, but has the
 	    advantage of being I/O efficient.  For an overview of this approach, see
-	    <a class="link" href="http://www.cloudera.com/content/cloudera/en/resources/library/hbasecon/video-hbasecon-2012-lessons-learned-from-opentsdb.html" target="_top">Lessons Learned from OpenTSDB</a>
-	    from HBaseCon2012.
-	    </p></div></div></div><div class="section" title="1.12.&nbsp;Operational and Performance Configuration Options"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="schema.ops"></a>1.12.&nbsp;Operational and Performance Configuration Options</h2></div></div></div><p>See the Performance section <a class="xref" href="#">???</a> for more information operational and performance
+	    <a class="xref" href="#">???</a>.
+	    </p></div></div><div class="section" title="1.11.5.&nbsp;Case Study - List Data"><div class="titlepage"><div><div><h3 class="title"><a name="casestudies.schema.listdata"></a>1.11.5.&nbsp;Case Study - List Data</h3></div></div></div><p>The following is an exchange from the user dist-list regarding a fairly common question:  
+    		how to handle per-user list data in Apache HBase. 
+    		</p><p>*** QUESTION ***</p><p>
+    		We're looking at how to store a large amount of (per-user) list data in
+HBase, and we were trying to figure out what kind of access pattern made
+the most sense.  One option is store the majority of the data in a key, so
+we could have something like:
+    		</p><pre class="programlisting">
+&lt;FixedWidthUserName&gt;&lt;FixedWidthValueId1&gt;:"" (no value)
+&lt;FixedWidthUserName&gt;&lt;FixedWidthValueId2&gt;:"" (no value)
+&lt;FixedWidthUserName&gt;&lt;FixedWidthValueId3&gt;:"" (no value)
+			</pre>
+
+The other option we had was to do this entirely using:
+    		<pre class="programlisting">
+&lt;FixedWidthUserName&gt;&lt;FixedWidthPageNum0&gt;:&lt;FixedWidthLength&gt;&lt;FixedIdNextPageNum&gt;&lt;ValueId1&gt;&lt;ValueId2&gt;&lt;ValueId3&gt;...
+&lt;FixedWidthUserName&gt;&lt;FixedWidthPageNum1&gt;:&lt;FixedWidthLength&gt;&lt;FixedIdNextPageNum&gt;&lt;ValueId1&gt;&lt;ValueId2&gt;&lt;ValueId3&gt;...
+    		</pre><p>
+where each row would contain multiple values.
+So in one case reading the first thirty values would be:
+			</p><pre class="programlisting">
+scan { STARTROW =&gt; 'FixedWidthUsername' LIMIT =&gt; 30}
+    		</pre>
+And in the second case it would be
+    		<pre class="programlisting">
+get 'FixedWidthUserName\x00\x00\x00\x00'
+    		</pre><p>
+The general usage pattern would be to read only the first 30 values of
+these lists, with infrequent access reading deeper into the lists.  Some
+users would have &lt;= 30 total values in these lists, and some users would
+have millions (i.e. power-law distribution)
+			</p><p>
+ The single-value format seems like it would take up more space on HBase,
+but would offer some improved retrieval / pagination flexibility.  Would
+there be any significant performance advantages to be able to paginate via
+gets vs paginating with scans?
+			</p><p>
+  My initial understanding was that doing a scan should be faster if our
+paging size is unknown (and caching is set appropriately), but that gets
+should be faster if we'll always need the same page size.  I've ended up
+hearing different people tell me opposite things about performance.  I
+assume the page sizes would be relatively consistent, so for most use cases
+we could guarantee that we only wanted one page of data in the
+fixed-page-length case.  I would also assume that we would have infrequent
+updates, but may have inserts into the middle of these lists (meaning we'd
+need to update all subsequent rows).
+			</p><p>
+Thanks for help / suggestions / follow-up questions.
+			</p><p>*** ANSWER ***</p><p>
+If I understand you correctly, you're ultimately trying to store
+triples in the form "user, valueid, value", right? E.g., something
+like:
+			</p><pre class="programlisting">
+"user123, firstname, Paul",
+"user234, lastname, Smith"
+			</pre><p>
+(But the usernames are fixed width, and the valueids are fixed width).
+			</p><p>
+And, your access pattern is along the lines of: "for user X, list the
+next 30 values, starting with valueid Y". Is that right? And these
+values should be returned sorted by valueid?
+			</p><p>
+The tl;dr version is that you should probably go with one row per
+user+value, and not build a complicated intra-row pagination scheme on
+your own unless you're really sure it is needed.
+			</p><p>
+Your two options mirror a common question people have when designing
+HBase schemas: should I go "tall" or "wide"? Your first schema is
+"tall": each row represents one value for one user, and so there are
+many rows in the table for each user; the row key is user + valueid,
+and there would be (presumably) a single column qualifier that means
+"the value". This is great if you want to scan over rows in sorted
+order by row key (thus my question above, about whether these ids are
+sorted correctly). You can start a scan at any user+valueid, read the
+next 30, and be done. What you're giving up is the ability to have
+transactional guarantees around all the rows for one user, but it
+doesn't sound like you need that. Doing it this way is generally
+recommended (see
+here <a class="link" href="http://hbase.apache.org/book.html#schema.smackdown" target="_top">http://hbase.apache.org/book.html#schema.smackdown</a>).
+			</p><p>
+Your second option is "wide": you store a bunch of values in one row,
+using different qualifiers (where the qualifier is the valueid). The
+simple way to do that would be to just store ALL values for one user
+in a single row. I'm guessing you jumped to the "paginated" version
+because you're assuming that storing millions of columns in a single
+row would be bad for performance, which may or may not be true; as
+long as you're not trying to do too much in a single request, or do
+things like scanning over and returning all of the cells in the row,
+it shouldn't be fundamentally worse. The client has methods that allow
+you to get specific slices of columns.
+			</p><p>
+Note that neither case fundamentally uses more disk space than the
+other; you're just "shifting" part of the identifying information for
+a value either to the left (into the row key, in option one) or to the
+right (into the column qualifiers in option 2). Under the covers,
+every key/value still stores the whole row key, and column family
+name. (If this is a bit confusing, take an hour and watch Lars
+George's excellent video about understanding HBase schema design:
+<a class="link" href="http://www.youtube.com/watch?v=_HLoH_PgrLk)" target="_top">http://www.youtube.com/watch?v=_HLoH_PgrLk)</a>.
+			</p><p>
+A manually paginated version has lots more complexities, as you note,
+like having to keep track of how many things are in each page,
+re-shuffling if new values are inserted, etc. That seems significantly
+more complex. It might have some slight speed advantages (or
+disadvantages!) at extremely high throughput, and the only way to
+really know that would be to try it out. If you don't have time to
+build it both ways and compare, my advice would be to start with the
+simplest option (one row per user+value). Start simple and iterate! :)
+			</p></div></div><div class="section" title="1.12.&nbsp;Operational and Performance Configuration Options"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="schema.ops"></a>1.12.&nbsp;Operational and Performance Configuration Options</h2></div></div></div><p>See the Performance section <a class="xref" href="#">???</a> for more information operational and performance
     schema design options, such as Bloom Filters, Table-configured regionsizes, compression, and blocksizes.
     </p></div></div><div id="disqus_thread"></div><script type="text/javascript">
     var disqus_shortname = 'hbase'; // required: replace example with your forum shortname