{"id":21032,"date":"2016-08-29T10:12:24","date_gmt":"2016-08-29T09:12:24","guid":{"rendered":"https:\/\/www.inovex.de\/?p=2103"},"modified":"2026-03-17T07:59:25","modified_gmt":"2026-03-17T06:59:25","slug":"hbase-and-phoenix-on-azure-adventures-in-abstraction","status":"publish","type":"post","link":"https:\/\/www.inovex.de\/de\/blog\/hbase-and-phoenix-on-azure-adventures-in-abstraction\/","title":{"rendered":"HBase and Phoenix on Azure: adventures in abstraction"},"content":{"rendered":"<p>One of my favourite essays by Joel Spolsky (he of Stack Overflow fame) is <a href=\"http:\/\/www.joelonsoftware.com\/articles\/LeakyAbstractions.html\" target=\"_blank\" rel=\"noopener\">\u201cThe law of leaky abstractions\u201c<\/a>. In it he describes how the prevalence of layers of abstraction \u2013 be it coding languages or libraries or frameworks \u2013 have helped us accelerate our productivity. We don\u2019t have to talk directly to a database engine because we can let our SQL do that for us; we don\u2019t have to implement map reduce jobs in java anymore because we can use Hive; we don\u2019t have to\u2026 well, you get the idea.<!--more--><\/p>\n<p>But he also points out that even the best frameworks and languages are less than perfect, and when things go awry, these frameworks \u201cleak\u201c the details of their abstraction out to the observing world. We are then confronted with all the nuts-and-bolts of the implementation that had been hitherto kindly hidden from us, and we often have no alternative but to busy ourselves with a depth of detail that we had not expected.<\/p>\n<p>Hadoop is a good case in point: consider my first Hadoop project in 2011, shown below on the left (\u201con premise\u201c) where we implemented most of the map-reduce jobs in java with a sprinkling of pig scripts.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-2104\" src=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2016\/08\/hbase-1-1024x648.png\" alt=\"on-premise-vs-cloud\" width=\"800\" height=\"506\" \/><\/p>\n<p>Compare that to the project we have just completed, running on Microsoft Azure, shown on the right (\u201ccloud\u201c).<\/p>\n<p>Note that we have added two extra layers of abstraction ourselves (HBase and Phoenix), but that the cloud stack has added another 2 (virtualization and azure storage).<\/p>\n<p>This is all fine\u2026 until things are not quite so fine \u2013 and then it is a non-trivial task finding the cause. In fact, on rare occasions you may even end up needing to know almost as much about the underlying implementation as if there had been no abstraction layer in the first place! With this as our background, I\u2019d like to offer the following:<\/p>\n<ol>\n<li>Some reflections on using Phoenix as an SQL layer over HBase<\/li>\n<li>Some comments on HBase compaction settings in the context of Azure<\/li>\n<\/ol>\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_83 counter-hierarchy ez-toc-counter ez-toc-custom ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\"><p class=\"ez-toc-title\" style=\"cursor:inherit\"><\/p>\n<\/div><nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/www.inovex.de\/de\/blog\/hbase-and-phoenix-on-azure-adventures-in-abstraction\/#Phoenix-and-HBase-%E2%80%93-a-friendship-with-benefits\" >Phoenix and HBase \u2013 a friendship with benefits?<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/www.inovex.de\/de\/blog\/hbase-and-phoenix-on-azure-adventures-in-abstraction\/#Compaction-distraction\" >Compaction distraction<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/www.inovex.de\/de\/blog\/hbase-and-phoenix-on-azure-adventures-in-abstraction\/#Phoenix-Indices-Co-location-and-HBase-splits\" >Phoenix Indices, Co-location and HBase splits<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/www.inovex.de\/de\/blog\/hbase-and-phoenix-on-azure-adventures-in-abstraction\/#Azure-Storage\" >Azure Storage<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/www.inovex.de\/de\/blog\/hbase-and-phoenix-on-azure-adventures-in-abstraction\/#Conclusion\" >Conclusion<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/www.inovex.de\/de\/blog\/hbase-and-phoenix-on-azure-adventures-in-abstraction\/#Read-on-%E2%80%A6\" >Read on &#8230;<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/www.inovex.de\/de\/blog\/hbase-and-phoenix-on-azure-adventures-in-abstraction\/#Join-us\" >Join us!<\/a><\/li><\/ul><\/nav><\/div>\n<h2><span class=\"ez-toc-section\" id=\"Phoenix-and-HBase-%E2%80%93-a-friendship-with-benefits\"><\/span>Phoenix and HBase \u2013 a friendship with benefits?<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>One of the aspects of using HBase is that there is normally (unless you are using the secondary index feature) only one rowkey and hence only one access path through the data: you can issue GETs or range SCANs using this key, but if any other access path is needed \u2013 i.e. you are searching for terms by anything other than rowkey (= get) or rowkey prefix (= scan) \u2013 then this will result in a full table scan. Since HBase and other components of the Hadoop stack are often used with unstructured data, this poses a challenge. What if we have stored our data using LASTNAME as the rowkey prefix but later realize that we want to search by FIRSTNAME as well?<\/p>\n<p>Apache Phoenix offers capabilities that can be used to escape this cul-de-sac: it is an SQL layer over HBase which offers the following features\/advantages relevant to our challenge:<\/p>\n<ol>\n<li>SQL syntax for retrieving HBase data, a nice alternative to using the native HBase API<\/li>\n<li>Secondary indices<\/li>\n<\/ol>\n<p>Phoenix secondary indices are implemented as co-processors (which, put simplistically, act as triggers, keeping the \u201cindex\u201c tables in sync with the \u201cparent\u201c tables) on the underlying HBase tables. A secondary index uses as its rowkey a combination of the column (or columns) that comprise the index plus the original rowkey, thus preserving uniqueness. You don\u2019t have to populate the index yourself, the co-processor will do that for you when you make changes to the parent table. The optimizer can then use this index as an alternative to the table named in the original query, allowing us to add indices to an existing table and letting the optimizer transparently choose the most appropriate access path. However, a number of things should be carefully noted:<\/p>\n<ol>\n<li>Phoenix can only track changes to the index if changes made to the parent data are made through Phoenix: you can read from the HBase table using standard HBase tools, but you should only make changes via Phoenix.<\/li>\n<li>Bulk loading a Phoenix table is theoretically possible using a number of tools (JDBC, Spark, Phoenix Map-Reduce jobs, Pig) that bridge the Phoenix- and HBase-worlds, but in practice this is anything but straightforward. <del>JDBC only writes line-by-line (JDBC batched writes are only available when using the Phoenix thin JDBC driver which uses the Avatica sub-project of the Calcite library: it is unclear which version contains this but most probably Avatica 1.8 \u2013&gt; Phoenix 4.6 or 4.7?)<\/del> (As <a href=\"https:\/\/twitter.com\/josh_elser\/status\/770299122012139520\" target=\"_blank\" rel=\"noopener\">Josh Elser told me<\/a>, Phoenix is indeed batching things implicitly with autocommit switched off. I stand corrected.), and the Spark and map-reduce jobs run into difficulties if there are too many indices on a table.<\/li>\n<li>The temptation with a tool offering SQL syntax is to assume that declarative set-based operations can be used freely (not an unreasonable assumption, since that is the purpose of SQL!). However, HBase is just not set up for anything other than single gets or discrete range scans, and Phoenix queries, particularly those that cannot use an index, may often result in timeouts.<\/li>\n<li>Phoenix indices can either be Global (each index is a separate HBase table in its own right), or Local. For the purposes of this article, the important thing to note is that Local indices are preferable since the index data is stored in the same region as the parent data, thus keeping internal RPC-calls to a minimum. They are also still officially in technical preview, and are undergoing <a href=\"https:\/\/issues.apache.org\/jira\/browse\/PHOENIX-1734\" target=\"_blank\" rel=\"noopener\">significant improvements<\/a>.<\/li>\n<li>Phoenix indices are separate from but affected by design decisions within HBase, not all of which have met with <a href=\"https:\/\/www.linkedin.com\/pulse\/secondary-indexing-hbase-tale-how-screw-up-simple-idea-michael-segel\" target=\"_blank\" rel=\"noopener\">unanimous approval<\/a>.<\/li>\n<\/ol>\n<h2><span class=\"ez-toc-section\" id=\"Compaction-distraction\"><\/span>Compaction distraction<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>As an aside, let\u2019s briefly discuss one of the concepts central to HBase: that of the <a href=\"http:\/\/citeseerx.ist.psu.edu\/viewdoc\/download;jsessionid=A42E7EDABC8D1592D1E1EA7806671590?doi=10.1.1.44.2782&amp;rep=rep1&amp;type=pdf\" target=\"_blank\" rel=\"noopener\">Log-structured Merge Tree<\/a> (also used in Lucene).<\/p>\n<p>HBase writes first to a write-ahead-log on disk, then to an in-memory store (memstore), and acknowledges the write only when both are successful. When the memstore reaches a certain (configured) size, it is flushed to disk and the WAL for that memstore is removed: this is great for writes, but not so great for reads, as there will be an increasing number of small files to access. HBase gets around this by periodically carrying out compactions, such that the individual store files are combined (again, this can be configured). Compactions come in two flavours:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-2198 size-large\" src=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2016\/08\/compaction-1024x481.png\" alt=\"HBase compaction diagram\" width=\"800\" height=\"376\" \/><\/p>\n<ol>\n<li>Minor compactions, whereby the individual store files belonging to a particular store (mapping to a single column family within an HBase table) are consolidated according to certain algorithms, as illustrated above. The blue bars represent new store files that are created when a memstore is flushed to disk, and the green bars represent compacted store files:<\/li>\n<li>Major compactions, whereby HBase attempts to combine all files for a store into a single file. I say \u201cattempts to\u201c, because if the resulting file exceeds the specified limit (defined by the property hbase.hregion.max.filesize), then HBase will split the region into two smaller regions. However, this split-region-when-compacted-file-reaches-max-limit rule is also subject to other factors (see next section).<\/li>\n<\/ol>\n<p>The settings pertinent to compaction behavior are:<\/p>\n<p><strong>hbase.hstore.compaction.min<\/strong> (previously called hbase.hstore.compactionThreshold): the minimum number of files needed for a minor compaction, set to a default of 3 in HBase and Azure\/HDInsight.<\/p>\n<p><strong>hbase.hstore.compaction.max:<\/strong> the maximum number of files considered for a compaction, set to a default of 10 in HBase and Azure\/HDInsight.<\/p>\n<p><strong>hbase.hstore.compaction.max.size:<\/strong> any file greater than this will be excluded from minor compactions. Set to Long.MAX_VALUE in HBase but limited to 10GB in Azure\/HDInsight.<\/p>\n<p><strong>hbase.hregion.majorcompaction:<\/strong> the time between major compactions in milliseconds. This defaults to 7 days in HBase, but is turned off in Azure\/HDInsight.<\/p>\n<p>hbase.hregion.max.filesize: when all files in a region reach this limit, the region is split in two. Set to a default of 10GB in HBase but to 3GB in Azure\/HDInsight.<\/p>\n<p><strong>hbase.hstore.blockingStoreFiles:<\/strong> a Store can only have this many files; if the number is exceeded a compaction is forced and further writes are blocked. Set to a default of 10 in HBase but increased to 100 in Azure\/HDInsight.<\/p>\n<p>So why, in the diagram shown above, did we not have a minor compaction at point B, where we again had three files available to us in the store? The reason is that the compaction algorithm (ExploringCompactionPolicy in HBase 0.96 and later; RatioBasedCompactionPolicy previously) takes into account the differing sizes of file, and excludes from a compaction any file whose size exceeds the size of the other files in the compaction-set by a given ratio. This prevents the store from having <a href=\"http:\/\/hbase.apache.org\/xref\/org\/apache\/hadoop\/hbase\/regionserver\/compactions\/ExploringCompactionPolicy.html\" target=\"_blank\" rel=\"noopener\">files with largely divergent sizes<\/a>. The full list of compaction-related parameters can be found on the <a href=\"https:\/\/hbase.apache.org\/book.html#compaction.parameters\" target=\"_blank\" rel=\"noopener\">official HBase website<\/a>.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Phoenix-Indices-Co-location-and-HBase-splits\"><\/span>Phoenix Indices, Co-location and HBase splits<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>I mentioned earlier that it is beneficial to use Local indexes with Phoenix: this is particularly true for read-heavy environments. When local indices is defined on a table, all index data is stored in a single subsidiary table, named:<\/p>\n<p><strong>_LOCAL_IDX_[parent-table-name]<\/strong><\/p>\n<p>In the HBase master UI you will then see something like this in the table description:<\/p>\n<p>&#8218;SPLIT_POLICY&#8216; =&gt; &#8218;org.apache.phoenix.hbase.index.IndexRegionSplitPolicy&#8216;<\/p>\n<p>This class overrides RegionSplitPolicy in order to prevent automatic splitting:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-2107\" src=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2016\/08\/hbase-split.png\" alt=\"hbase-split\" width=\"945\" height=\"352\" \/><\/p>\n<p>This may seem strange, but makes sense when one considers that local index data should be co-located with the parent data, meaning that the index table is only split when the parent table is split.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Azure-Storage\"><\/span>Azure Storage<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Enter Azure Storage, another cog in the machine. This layer of abstraction introduces another factor: how to efficiently read from and write to the \u201cblob\u201c objects that make up azure storage. Even though the Azure documentation states that a Blob may consist of up to 50,000 blocks, with each block having a default size of 4MB \u2013 meaning that with default settings we can write single files up to 200GB \u2013 this needs to be understood in the context of the default Azure HBase\/HDFS settings (<strong>fs.azure.read.request.size<\/strong> and <strong>fs.azure.write.request.size<\/strong>), which sets the block size for read\/write activity to 256 KB, for performance reasons. The side effect of this is that we can only read and write files to Azure Storage that do not exceed 50,000 x 256 KB = 12 GB.<\/p>\n<p>Attentive readers may by now have a sense of impending doom: the HBase defaults are fine for the majority of cases, though these have been tweaked in HDInsight to avoid performance issues when reading and writing large files (abstraction #1). However, Phoenix \u2013 bundled with HBase in HDInsight \u2013 derives the most benefit from local indices when splitting is determined by the parent table, not the table holding the index data, and this is implemented (i.e. automatic splits are blocked) when a local index is created (abstraction #2). If we have several indices created on a table, then the index table may grow to be several times the size of the parent table, particularly if covering indices (when other columns other than those that form the index are stored along with the index) are used.<\/p>\n<p>In our case, we were observing blocked splits on the index table (because splitting is determined by the parent table to ensure co-location), leading to store files that were too large to be compacted, resulting in exceptions like this:<\/p>\n<p>regionserver.CompactSplitThread: Compaction failed Request = regionName=_LOCAL_IDX_[parent table name]\u2026<\/p>\n<pre class=\"lang:java decode:true \">java.io.IOException\r\n\r\n        at com.microsoft.azure.storage.core.Utility.initIOException(Utility.java:643)\r\n\r\n        at com.microsoft.azure.storage.blob.BlobOutputStream.close(BlobOutputStream.java:280)\r\n\r\n        at java.io.FilterOutputStream.close(FilterOutputStream.java:160)\r\n\r\n        at org.apache.hadoop.fs.azure.NativeAzureFileSystem$NativeAzureFsOutputStream.close(NativeAzureFileSystem.java:869)\r\n\r\n        at org.apache.hadoop.fs.FSDataOutputStream$PositionCache.close(FSDataOutputStream.java:72)\r\n\r\n        at org.apache.hadoop.fs.FSDataOutputStream.close(FSDataOutputStream.java:106)\r\n\r\n        at org.apache.hadoop.hbase.io.hfile.AbstractHFileWriter.finishClose(AbstractHFileWriter.java:248)\r\n\r\n        at org.apache.hadoop.hbase.io.hfile.HFileWriterV3.finishClose(HFileWriterV3.java:133)\r\n\r\n        at org.apache.hadoop.hbase.io.hfile.HFileWriterV2.close(HFileWriterV2.java:366)\r\n\r\n        at org.apache.hadoop.hbase.regionserver.StoreFile$Writer.close(StoreFile.java:996)\r\n\r\n        at org.apache.hadoop.hbase.regionserver.compactions.DefaultCompactor.compact(DefaultCompactor.java:133)\r\n\r\n        at org.apache.hadoop.hbase.regionserver.DefaultStoreEngine$DefaultCompactionContext.compact(DefaultStoreEngine.java:112)\r\n\r\n        at org.apache.hadoop.hbase.regionserver.HStore.compact(HStore.java:1212)\r\n\r\n        at org.apache.hadoop.hbase.regionserver.HRegion.compact(HRegion.java:1806)\r\n\r\n        at org.apache.hadoop.hbase.regionserver.CompactSplitThread$CompactionRunner.run(CompactSplitThread.java:519)\r\n\r\n        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)\r\n\r\n        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)\r\n\r\n        at java.lang.Thread.run(Thread.java:745)\r\n\r\nCaused by: com.microsoft.azure.storage.StorageException: The request body is too large and exceeds the maximum permissible limit.\r\n\r\n        at com.microsoft.azure.storage.StorageException.translateException(StorageException.java:89)\r\n\r\n        at com.microsoft.azure.storage.core.StorageRequest.materializeException(StorageRequest.java:307)\r\n\r\n        at com.microsoft.azure.storage.core.ExecutionEngine.executeWithRetry(ExecutionEngine.java:182)\r\n\r\n        at com.microsoft.azure.storage.blob.CloudBlockBlob.commitBlockList(CloudBlockBlob.java:245)\r\n\r\n        at com.microsoft.azure.storage.blob.BlobOutputStream.commit(BlobOutputStream.java:313)\r\n\r\n        at com.microsoft.azure.storage.blob.BlobOutputStream.close(BlobOutputStream.java:277)\r\n\r\n        ... 16 more<\/pre>\n<p>Two independent sets of behavior \u2013 both abstracted enough away from view to be difficult to find \u2013 were working against each other.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Conclusion\"><\/span>Conclusion<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>In our situation we decided to keep major compactions turned off, and to only manually execute them in combination with temporarily increasing the azure storage settings (<strong>fs.azure.read.request.size<\/strong> and <strong>fs.azure.write.request.size<\/strong>). In this way we could rely on the minor compaction algorithm to keep the individual store files within the correct limit. However, we also discovered that there is often no substitute to rolling up your sleeves and seeking to understand the many and varied configuration settings, as well as wading through source code to gain a better understanding of such corner-case behavior.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Read-on-%E2%80%A6\"><\/span>Read on &#8230;<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>So you&#8217;re interested in processing heaps of data? Have a look at <a href=\"https:\/\/www.inovex.de\/en\/our-services\/big-data\/\" target=\"_blank\" rel=\"noopener\">our website<\/a> and read about the services we offer to our customers.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Join-us\"><\/span>Join us!<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Are you looking for a job in big data processing or analytics? We&#8217;re currently hiring!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>One of my favourite essays by Joel Spolsky (he of Stack Overflow fame) is \u201cThe law of leaky abstractions\u201c. In it he describes how the prevalence of layers of abstraction \u2013 be it coding languages or libraries or frameworks \u2013 have helped us accelerate our productivity. We don\u2019t have to talk directly to a database [&hellip;]<\/p>\n","protected":false},"author":49,"featured_media":2197,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"ep_exclude_from_search":false,"footnotes":""},"tags":[77],"service":[411],"coauthors":[{"id":49,"display_name":"Andrew Kenworthy","user_nicename":"akenworthy"}],"class_list":["post-21032","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","tag-big-data","service-data-engineering"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.7 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>HBase and Phoenix on Azure: adventures in abstraction - inovex GmbH<\/title>\n<meta name=\"description\" content=\"Layers of abstraction have helped us accelerate our productivity \u2013 but if they fail we are confronted with all the nuts-and-bolts of the implementation.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.inovex.de\/de\/blog\/hbase-and-phoenix-on-azure-adventures-in-abstraction\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"HBase and Phoenix on Azure: adventures in abstraction - inovex GmbH\" \/>\n<meta property=\"og:description\" content=\"Layers of abstraction have helped us accelerate our productivity \u2013 but if they fail we are confronted with all the nuts-and-bolts of the implementation.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.inovex.de\/de\/blog\/hbase-and-phoenix-on-azure-adventures-in-abstraction\/\" \/>\n<meta property=\"og:site_name\" content=\"inovex GmbH\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/inovexde\" \/>\n<meta property=\"article:published_time\" content=\"2016-08-29T09:12:24+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-03-17T06:59:25+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2016\/08\/hbase-phoenix-azure.png\" \/>\n\t<meta property=\"og:image:width\" content=\"2300\" \/>\n\t<meta property=\"og:image:height\" content=\"876\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Andrew Kenworthy\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:image\" content=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2016\/08\/hbase-phoenix-azure-1024x390.png\" \/>\n<meta name=\"twitter:creator\" content=\"@inovexgmbh\" \/>\n<meta name=\"twitter:site\" content=\"@inovexgmbh\" \/>\n<meta name=\"twitter:label1\" content=\"Verfasst von\" \/>\n\t<meta name=\"twitter:data1\" content=\"Andrew Kenworthy\" \/>\n\t<meta name=\"twitter:label2\" content=\"Gesch\u00e4tzte Lesezeit\" \/>\n\t<meta name=\"twitter:data2\" content=\"12\u00a0Minuten\" \/>\n\t<meta name=\"twitter:label3\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data3\" content=\"Andrew Kenworthy\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/hbase-and-phoenix-on-azure-adventures-in-abstraction\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/hbase-and-phoenix-on-azure-adventures-in-abstraction\\\/\"},\"author\":{\"name\":\"Andrew Kenworthy\",\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/#\\\/schema\\\/person\\\/0519169c755e15b1478ccf638f16f06c\"},\"headline\":\"HBase and Phoenix on Azure: adventures in abstraction\",\"datePublished\":\"2016-08-29T09:12:24+00:00\",\"dateModified\":\"2026-03-17T06:59:25+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/hbase-and-phoenix-on-azure-adventures-in-abstraction\\\/\"},\"wordCount\":2055,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/hbase-and-phoenix-on-azure-adventures-in-abstraction\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.inovex.de\\\/wp-content\\\/uploads\\\/2016\\\/08\\\/hbase-phoenix-azure.png\",\"keywords\":[\"Big Data\"],\"articleSection\":[\"Analytics\",\"English Content\",\"General\"],\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/hbase-and-phoenix-on-azure-adventures-in-abstraction\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/hbase-and-phoenix-on-azure-adventures-in-abstraction\\\/\",\"url\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/hbase-and-phoenix-on-azure-adventures-in-abstraction\\\/\",\"name\":\"HBase and Phoenix on Azure: adventures in abstraction - inovex GmbH\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/hbase-and-phoenix-on-azure-adventures-in-abstraction\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/hbase-and-phoenix-on-azure-adventures-in-abstraction\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.inovex.de\\\/wp-content\\\/uploads\\\/2016\\\/08\\\/hbase-phoenix-azure.png\",\"datePublished\":\"2016-08-29T09:12:24+00:00\",\"dateModified\":\"2026-03-17T06:59:25+00:00\",\"description\":\"Layers of abstraction have helped us accelerate our productivity \u2013 but if they fail we are confronted with all the nuts-and-bolts of the implementation.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/hbase-and-phoenix-on-azure-adventures-in-abstraction\\\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/hbase-and-phoenix-on-azure-adventures-in-abstraction\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/hbase-and-phoenix-on-azure-adventures-in-abstraction\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.inovex.de\\\/wp-content\\\/uploads\\\/2016\\\/08\\\/hbase-phoenix-azure.png\",\"contentUrl\":\"https:\\\/\\\/www.inovex.de\\\/wp-content\\\/uploads\\\/2016\\\/08\\\/hbase-phoenix-azure.png\",\"width\":2300,\"height\":876,\"caption\":\"hbase und phoenix auf Azure\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/hbase-and-phoenix-on-azure-adventures-in-abstraction\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"HBase and Phoenix on Azure: adventures in abstraction\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/#website\",\"url\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/\",\"name\":\"inovex GmbH\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"de\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/#organization\",\"name\":\"inovex GmbH\",\"url\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.inovex.de\\\/wp-content\\\/uploads\\\/2021\\\/03\\\/inovex-logo-16-9-1.png\",\"contentUrl\":\"https:\\\/\\\/www.inovex.de\\\/wp-content\\\/uploads\\\/2021\\\/03\\\/inovex-logo-16-9-1.png\",\"width\":1921,\"height\":1081,\"caption\":\"inovex GmbH\"},\"image\":{\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/inovexde\",\"https:\\\/\\\/x.com\\\/inovexgmbh\",\"https:\\\/\\\/www.instagram.com\\\/inovexlife\\\/\",\"https:\\\/\\\/www.linkedin.com\\\/company\\\/inovex\",\"https:\\\/\\\/www.youtube.com\\\/channel\\\/UC7r66GT14hROB_RQsQBAQUQ\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/#\\\/schema\\\/person\\\/0519169c755e15b1478ccf638f16f06c\",\"name\":\"Andrew Kenworthy\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/c7a29df25f27010b3c581f97c66a52694571cfa2f9c9b79049542969194fbdd3?s=96&d=retro&r=g7397755342ed757eeb6b1d51f16a4044\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/c7a29df25f27010b3c581f97c66a52694571cfa2f9c9b79049542969194fbdd3?s=96&d=retro&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/c7a29df25f27010b3c581f97c66a52694571cfa2f9c9b79049542969194fbdd3?s=96&d=retro&r=g\",\"caption\":\"Andrew Kenworthy\"},\"url\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/author\\\/akenworthy\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"HBase and Phoenix on Azure: adventures in abstraction - inovex GmbH","description":"Layers of abstraction have helped us accelerate our productivity \u2013 but if they fail we are confronted with all the nuts-and-bolts of the implementation.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.inovex.de\/de\/blog\/hbase-and-phoenix-on-azure-adventures-in-abstraction\/","og_locale":"de_DE","og_type":"article","og_title":"HBase and Phoenix on Azure: adventures in abstraction - inovex GmbH","og_description":"Layers of abstraction have helped us accelerate our productivity \u2013 but if they fail we are confronted with all the nuts-and-bolts of the implementation.","og_url":"https:\/\/www.inovex.de\/de\/blog\/hbase-and-phoenix-on-azure-adventures-in-abstraction\/","og_site_name":"inovex GmbH","article_publisher":"https:\/\/www.facebook.com\/inovexde","article_published_time":"2016-08-29T09:12:24+00:00","article_modified_time":"2026-03-17T06:59:25+00:00","og_image":[{"width":2300,"height":876,"url":"https:\/\/www.inovex.de\/wp-content\/uploads\/2016\/08\/hbase-phoenix-azure.png","type":"image\/png"}],"author":"Andrew Kenworthy","twitter_card":"summary_large_image","twitter_image":"https:\/\/www.inovex.de\/wp-content\/uploads\/2016\/08\/hbase-phoenix-azure-1024x390.png","twitter_creator":"@inovexgmbh","twitter_site":"@inovexgmbh","twitter_misc":{"Verfasst von":"Andrew Kenworthy","Gesch\u00e4tzte Lesezeit":"12\u00a0Minuten","Written by":"Andrew Kenworthy"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.inovex.de\/de\/blog\/hbase-and-phoenix-on-azure-adventures-in-abstraction\/#article","isPartOf":{"@id":"https:\/\/www.inovex.de\/de\/blog\/hbase-and-phoenix-on-azure-adventures-in-abstraction\/"},"author":{"name":"Andrew Kenworthy","@id":"https:\/\/www.inovex.de\/de\/#\/schema\/person\/0519169c755e15b1478ccf638f16f06c"},"headline":"HBase and Phoenix on Azure: adventures in abstraction","datePublished":"2016-08-29T09:12:24+00:00","dateModified":"2026-03-17T06:59:25+00:00","mainEntityOfPage":{"@id":"https:\/\/www.inovex.de\/de\/blog\/hbase-and-phoenix-on-azure-adventures-in-abstraction\/"},"wordCount":2055,"commentCount":0,"publisher":{"@id":"https:\/\/www.inovex.de\/de\/#organization"},"image":{"@id":"https:\/\/www.inovex.de\/de\/blog\/hbase-and-phoenix-on-azure-adventures-in-abstraction\/#primaryimage"},"thumbnailUrl":"https:\/\/www.inovex.de\/wp-content\/uploads\/2016\/08\/hbase-phoenix-azure.png","keywords":["Big Data"],"articleSection":["Analytics","English Content","General"],"inLanguage":"de","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.inovex.de\/de\/blog\/hbase-and-phoenix-on-azure-adventures-in-abstraction\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.inovex.de\/de\/blog\/hbase-and-phoenix-on-azure-adventures-in-abstraction\/","url":"https:\/\/www.inovex.de\/de\/blog\/hbase-and-phoenix-on-azure-adventures-in-abstraction\/","name":"HBase and Phoenix on Azure: adventures in abstraction - inovex GmbH","isPartOf":{"@id":"https:\/\/www.inovex.de\/de\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.inovex.de\/de\/blog\/hbase-and-phoenix-on-azure-adventures-in-abstraction\/#primaryimage"},"image":{"@id":"https:\/\/www.inovex.de\/de\/blog\/hbase-and-phoenix-on-azure-adventures-in-abstraction\/#primaryimage"},"thumbnailUrl":"https:\/\/www.inovex.de\/wp-content\/uploads\/2016\/08\/hbase-phoenix-azure.png","datePublished":"2016-08-29T09:12:24+00:00","dateModified":"2026-03-17T06:59:25+00:00","description":"Layers of abstraction have helped us accelerate our productivity \u2013 but if they fail we are confronted with all the nuts-and-bolts of the implementation.","breadcrumb":{"@id":"https:\/\/www.inovex.de\/de\/blog\/hbase-and-phoenix-on-azure-adventures-in-abstraction\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.inovex.de\/de\/blog\/hbase-and-phoenix-on-azure-adventures-in-abstraction\/"]}]},{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/www.inovex.de\/de\/blog\/hbase-and-phoenix-on-azure-adventures-in-abstraction\/#primaryimage","url":"https:\/\/www.inovex.de\/wp-content\/uploads\/2016\/08\/hbase-phoenix-azure.png","contentUrl":"https:\/\/www.inovex.de\/wp-content\/uploads\/2016\/08\/hbase-phoenix-azure.png","width":2300,"height":876,"caption":"hbase und phoenix auf Azure"},{"@type":"BreadcrumbList","@id":"https:\/\/www.inovex.de\/de\/blog\/hbase-and-phoenix-on-azure-adventures-in-abstraction\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.inovex.de\/de\/"},{"@type":"ListItem","position":2,"name":"HBase and Phoenix on Azure: adventures in abstraction"}]},{"@type":"WebSite","@id":"https:\/\/www.inovex.de\/de\/#website","url":"https:\/\/www.inovex.de\/de\/","name":"inovex GmbH","description":"","publisher":{"@id":"https:\/\/www.inovex.de\/de\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.inovex.de\/de\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"de"},{"@type":"Organization","@id":"https:\/\/www.inovex.de\/de\/#organization","name":"inovex GmbH","url":"https:\/\/www.inovex.de\/de\/","logo":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/www.inovex.de\/de\/#\/schema\/logo\/image\/","url":"https:\/\/www.inovex.de\/wp-content\/uploads\/2021\/03\/inovex-logo-16-9-1.png","contentUrl":"https:\/\/www.inovex.de\/wp-content\/uploads\/2021\/03\/inovex-logo-16-9-1.png","width":1921,"height":1081,"caption":"inovex GmbH"},"image":{"@id":"https:\/\/www.inovex.de\/de\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/inovexde","https:\/\/x.com\/inovexgmbh","https:\/\/www.instagram.com\/inovexlife\/","https:\/\/www.linkedin.com\/company\/inovex","https:\/\/www.youtube.com\/channel\/UC7r66GT14hROB_RQsQBAQUQ"]},{"@type":"Person","@id":"https:\/\/www.inovex.de\/de\/#\/schema\/person\/0519169c755e15b1478ccf638f16f06c","name":"Andrew Kenworthy","image":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/secure.gravatar.com\/avatar\/c7a29df25f27010b3c581f97c66a52694571cfa2f9c9b79049542969194fbdd3?s=96&d=retro&r=g7397755342ed757eeb6b1d51f16a4044","url":"https:\/\/secure.gravatar.com\/avatar\/c7a29df25f27010b3c581f97c66a52694571cfa2f9c9b79049542969194fbdd3?s=96&d=retro&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/c7a29df25f27010b3c581f97c66a52694571cfa2f9c9b79049542969194fbdd3?s=96&d=retro&r=g","caption":"Andrew Kenworthy"},"url":"https:\/\/www.inovex.de\/de\/blog\/author\/akenworthy\/"}]}},"_links":{"self":[{"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/posts\/21032","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/users\/49"}],"replies":[{"embeddable":true,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/comments?post=21032"}],"version-history":[{"count":2,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/posts\/21032\/revisions"}],"predecessor-version":[{"id":66512,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/posts\/21032\/revisions\/66512"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/media\/2197"}],"wp:attachment":[{"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/media?parent=21032"}],"wp:term":[{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/tags?post=21032"},{"taxonomy":"service","embeddable":true,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/service?post=21032"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/coauthors?post=21032"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}