<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="https://www.w3.org/2005/Atom" xmlns:sy="https://purl.org/rss/1.0/modules/syndication/" xmlns:dc="https://purl.org/dc/elements/1.1/" xmlns:content="https://purl.org/rss/1.0/modules/content/" xmlns:wfw="https://wellformedweb.org/CommentAPI/" xmlns:slash="https://purl.org/rss/1.0/modules/slash/"
  version="2.0">
  <channel>
    <title>Bluewater SQL</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/bluewatersql/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/bluewatersql/feed.xml</link>
    <description>Business Intelligence, Big Data &amp;amp; Other Ramblings</description>
    <lastBuildDate>Wed, 17 Apr 2019 03:19:07 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>Using #PolyBase in #SQLServer2016</title>
      <link>https://docs.microsoft.com/archive/blogs/bluewatersql/using-polybase-in-sqlserver2016</link>
      <pubDate>Wed, 03 Jun 2015 10:57:00 GMT</pubDate>
      <dc:creator><![CDATA[Bluewater SQL]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/bluewatersql/2015/06/03/using-polybase-in-sqlserver2016/</guid>
      <description><![CDATA[It&rsquo;s been a few weeks since the numerous Build and Ignite announcements ushered in the latest...]]></description>
      <content:encoded><![CDATA[<p>It&rsquo;s been a few weeks since the numerous Build and Ignite announcements ushered in the latest and greatest, SQL Server 2016. After having some time to soak it up (aka I&rsquo;ve been too busy to blog) we will dive into some of features and capabilities I find most interesting.</p>
<h3>Poly-what?</h3>
<p>While there are many new features and long overdue updates one of the most interesting is the introduction of PolyBase to the SQL Server platform. For those who have not heard or worked with PolyBase, it is not a totally new feature as it has existed on the PDW&hellip;err APS appliance for sometime now. So what is it? In short, PolyBase allows you to use your vast array of T-SQL ninja skills to query, join and manipulate unstructured or semi-structure data stored either in HDFS or Azure Blob Storage directly from the SQL Server relational environment all without learning or understanding the first thing about Java, Map/Reduce, Hive or any of the other big data technologies you&rsquo;ve heard buzzing around. So let&rsquo;s see how this works.</p>
<h3>Hands-On</h3>
<p>A a pre-requisite this post assumes you have an Azure account. If you don&rsquo;t have one&hellip;.shame on you&hellip;just kidding, you can sign-up for an account and even receive a free $200 trial credit. If you have an MSDN membership you may be eligible for a MSDN Azure account that provides $150 a month in Azure credits. With that out of the way let&rsquo;s build out a SQL Server 2016 sandbox. Begin by signing into the <a href="https://manage.windowsazure.com/" target="_blank">Azure management portal</a>. From the portal home page, click the &lsquo;+ New&rsquo; button, then select Compute, Virtual Machine and From Gallery.</p>
<p><a href="https://bluewatersql.files.wordpress.com/2015/06/image1.png"><img style="display: inline; border-width: 0;" title="image" src="https://bluewatersql.files.wordpress.com/2015/06/image_thumb1.png" alt="image" width="587" height="279" border="0" /></a></p>
<p>The virtual machine gallery consist of all sorts of pre-built VM images that you can select from to simplify the set-up/install process. In our case, we are interested in the SQL Server 2016 CPT2 image found under the SQL Server group.</p>
<p><a href="https://bluewatersql.files.wordpress.com/2015/06/image2.png"><img style="display: inline; border-width: 0;" title="image" src="https://bluewatersql.files.wordpress.com/2015/06/image_thumb2.png" alt="image" width="479" height="312" border="0" /></a></p>
<p>During the set-up I recommend using a minimum VM size of A4 (8 cores, 16Gb memory) although this can vary depending on the size of the sample data you will be playing. After making you configuration selections, fight back the anticipation as your VM will be spun up and ready to go within a few minutes. Once your VM shows as ready on the Virtual Machine dashboard, you can select it and navigate to the dashboard. From the dashboard, you can use the Connect button to initiate a remote desktop session using the credential you specified during set-up.</p>
<p><a href="https://bluewatersql.files.wordpress.com/2015/06/image3.png"><img style="display: inline; border-width: 0;" title="image" src="https://bluewatersql.files.wordpress.com/2015/06/image_thumb3.png" alt="image" width="606" height="151" border="0" /></a></p>
<p>Because you use started with a pre-defined image, SQL Server 2016 is already set-up and ready to go sans PolyBase. To add the PolyBase functionality we much run through the installer, but before we can do that, you much update the Java JRE to a version of 7u55 or higher (<a title="https://www.oracle.com/technetwork/java/javase/downloads/index.html" href="https://www.oracle.com/technetwork/java/javase/downloads/index.html">https://www.oracle.com/technetwork/java/javase/downloads/index.html</a>). After that is complete, launch the SQL Server 2016 installer which is found at: C:\SQLServer_13.0_Full. Click the Next prompts through the process to Add a Feature to an Existing Installation and then simply select PolyBase. The install may take several minutes and then you are really, really ready to go.</p>
<p><a href="https://bluewatersql.files.wordpress.com/2015/06/image4.png"><img style="display: inline; border-width: 0;" title="image" src="https://bluewatersql.files.wordpress.com/2015/06/image_thumb4.png" alt="image" width="495" height="377" border="0" /></a></p>
<p>Open SQL Server Management Studio (SSMS) and connect to the local, SQL 2016 instance. By default, PolyBase integration is turned off. To enable it use the following command and then restart the SQL Server instance.</p>
<pre class="csharpcode"><span class="kwrd">EXEC</span> sp_configure <span class="str">'hadoop connectivity'</span>, 4; 
<span class="kwrd">GO</span> 
<span class="kwrd">RECONFIGURE</span>; 
<span class="kwrd">GO</span></pre>
<p>For this demo, we use the 4 option which indicates that we will be using HDInsight or Azure Blob Storage for PolyBase. There are other options for both Cloudera and Hortonworks Hadoop distributes available. After ensuring you have restarted the instance, you are ready to use PolyBase.</p>
<h3>Data Source, File Formats and External Tables</h3>
<p>These are three parts of PolyBase that you will need to familiarize yourself with and the MSDN documentation is a great reference as you move beyond the simplistic example given in this post. First we will create a data source. Since, we are using an Azure Blob Storage account, we must first create a credential that will be used to pass the access key to our storage account. The script below will create the database credential with the secret key required to access the blob storage account.</p>
<pre class="csharpcode">DBCC TRACEON(4631,-1);

CREATE MASTER KEY ENCRYPTION BY PASSWORD=<span class="str">'MyP@ssword123'</span>;

CREATE CREDENTIAL wasb_bluewaterdata 
ON DATABASE WITH
 IDENTITY = <span class="str">'bluewaterdata'</span>, 
SECRET=<span class="str">'&lt;MY SECRET KEY /&gt;'</span>;</pre>
<p>Once the credential is in place, we can define a data source which references a specific container on a blob storage account using the above credential like so:</p>
<pre class="csharpcode">CREATE EXTERNAL DATA SOURCE taxidata
WITH (
    TYPE = HADOOP,
    LOCATION = <span class="str">'wasbs://&lt;CONTAINER /&gt;@&lt;ACCOUNT /&gt;.blob.core.windows.net/'</span>,
    CREDENTIAL = wasb_bluewaterdata
);</pre>
<p>Next, we need to create the file format to tell PolyBase how to read the contents of the blobs. In this example, we are simply reading comma-delimited CSV files so our file format will be as follows.</p>
<pre class="csharpcode">CREATE EXTERNAL FILE FORMAT CSV 
WITH ( 
    FORMAT_TYPE = DELIMITEDTEXT, 
    FORMAT_OPTIONS ( 
        FIELD_TERMINATOR = <span class="str">','</span>
    ) 
);</pre>
<p>With the two foundational pieces out of the way, we are ready to create a table over top of our &ldquo;big&rdquo; data. The example I am using for this post is the NYC Taxi data I used in a previous post. This data as mention before is NYC Taxi trips and fare data in CSV format and includes a header row. I can define an external table that matches the file format as seen below, noting that I&rsquo;ve referenced my data source, file format and the file folder that contains the data. I also want to point out reject type and value, which in this case accommodates the header row found in the file.</p>
<pre class="csharpcode">CREATE EXTERNAL TABLE trips 
( 
    medallion VARCHAR(255),
    hack_license VARCHAR(255),
    vendor_id VARCHAR(255),
    rate_code VARCHAR(255),
    store_and_fwd_flag VARCHAR(255),
    pickup_datetime VARCHAR(255),
    dropoff_datetime VARCHAR(255),
    passenger_count INT,
    trip_time_in_secs INT,
    trip_distance FLOAT,
    pickup_longitude VARCHAR(255),
    pickup_latitude VARCHAR(255),
    dropoff_longitude VARCHAR(255),
    dropoff_latitude VARCHAR(255)
) 
WITH 
( 
    LOCATION = <span class="str">'/trips_small'</span>, 
    DATA_SOURCE = taxidata, 
    FILE_FORMAT = CSV,
    REJECT_TYPE = <span class="kwrd">value</span>, 
    REJECT_VALUE=1 
)</pre>
<p><a href="https://bluewatersql.files.wordpress.com/2015/06/image5.png"><img style="display: inline; border-width: 0;" title="image" src="https://bluewatersql.files.wordpress.com/2015/06/image_thumb5.png" alt="image" width="269" height="413" border="0" /></a></p>
<p>With my data source, file format and external table created, I can find all three new objects in the SSMS Object Explorer as seen in the screenshot above. I can also query, join or manipulate the data referenced by the new external table like any other SQL Server table all without the data ever residing directly in the SQL Server database. I included a few sample queries that were run directly against the objects created above to round out the demo.</p>
<table style="width: 100%;" border="0" cellspacing="0" cellpadding="2">
<tbody>
<tr>
<td valign="top"><a href="https://bluewatersql.files.wordpress.com/2015/06/image6.png"><img style="display: inline; border-width: 0;" title="image" src="https://bluewatersql.files.wordpress.com/2015/06/image_thumb6.png" alt="image" width="354" height="235" border="0" /></a></td>
</tr>
<tr>
<td valign="top"><a href="https://bluewatersql.files.wordpress.com/2015/06/image7.png"><img style="display: inline; border-width: 0;" title="image" src="https://bluewatersql.files.wordpress.com/2015/06/image_thumb7.png" alt="image" width="374" height="471" border="0" /></a></td>
</tr>
</tbody>
</table>
<h3>Wrap-Up</h3>
<p>PolyBase is one more tool to help you bridge the gap between your relational and non-relational data stores through the use of your existing SQL skill set. I hope this post served as a general introduction to this technologies capabilities and why it is such an important piece to the SQL Server 2016 release. I also want to point out that as this entire post was written for SQL Server 2016 CTP 2, it is all subject to change before go live. Till next time!</p>
<h1>Chris</h1>]]></content:encoded>
    </item>
    <item>
      <title>Geospatial Queries Using Hive</title>
      <link>https://docs.microsoft.com/archive/blogs/bluewatersql/geospatial-queries-using-hive</link>
      <pubDate>Tue, 02 Jun 2015 08:04:39 GMT</pubDate>
      <dc:creator><![CDATA[Bluewater SQL]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/bluewatersql/2015/06/02/geospatial-queries-using-hive/</guid>
      <description><![CDATA[During one recent engagement, I was helping my customer align ETL activities that were originally...]]></description>
      <content:encoded><![CDATA[<p>During one recent engagement, I was helping my customer align ETL activities that were originally developed using SQL Server and T-SQL with the capabilities that were available using Hadoop and Hive. Most of the translations where straight-forward but when asked about geospatial support in Hive I was admittedly stumped. After full disclosure to the customer that I am not a geospatial expert I began digging for an answer. Knowing that most if not all of the query functionality available in Hive happens through the use of user-define functions (UDFs), I began my research by looking to see if someone else had already skinned the proverbial cat and I found a gold-mine. ESRI, a provider of GIS software, has not only already solved the problem, but has provided their toolkit of Hive functions to the open-source community via GitHub (get it <a href="https://github.com/Esri/spatial-framework-for-hadoop" target="_blank">HERE</a>). For the remainder of this post, I will review the steps necessary to set-up and use this toolkit but also walk through a real-world demo.</p>
<h3>Set-Up</h3>
<p>To begin, there are two JAR files needed:</p>
<ul>
<li>ersi-geometry-api.jar &ndash; contains all the base/foundational classes</li>
<li>spatial-sdk-hadoop.jar &ndash; contains UDF and serde implementations</li>
</ul>
<p>Since you can download these jar files already compiled from the ESRI GitHub site, I&rsquo;ll forgo the particulars on building each from its source and get right into the steps required to run these on a HDInsight cluster.</p>
<ol>
<li>Upload both jar files to a container in your blob storage account. Make note of whatever folder/directory structure you use.</li>
<li>Use the following to format the path to your the jar files:
<ul>
<li>wasb://&lt;container&gt;@&lt;account&gt;.blob.core.windows.net/&lt;directory&gt;/esri-geometry-api.jar</li>
<li>wasb://&lt;container&gt;@&lt;account&gt;.blob.core.windows.net/&lt;directory&gt;/spatial-sdk-hadoop.jar</li>
</ul>
</li>
<li>Using the Hive CLI or the HDInsight Query Console, declare both jar files or alternatively this can be done at the time of you spin up your cluster.
<pre class="csharpcode">add jar wasb:<span class="rem">//&lt;container&gt;@&lt;account&gt;.blob.core.windows.net/&lt;directory&gt;/esri-geometry-api.jar;</span>
add jar wasb://&lt;container&gt;@&lt;account&gt;.blob.core.windows.net/&lt;directory&gt;/spatial-sdk-hadoop.jar;</pre>
</li>
<li>For each function that you intend to use, you declare a temporary function as seen in the example. Note that Hive v0.13 supports permanent functions if you will be making wide spread use of these functions.
<pre class="csharpcode">create temporary function ST_Point <span class="kwrd">as</span> <span class="str">'com.esri.hadoop.hive.ST_Point'</span>;
create temporary function ST_Intersects <span class="kwrd">as</span> &lsquo;com.esri.hadoop.hive.ST_Intersects';</pre>
</li>
</ol>
<p>Now your ready to test. To test these functions without a spatial data set we can use two fixed points defined by their latitude and longitude. Since I spend an inordinate amount of time on an airplane, I&rsquo;ve picked a point near La Guardia International (LGA) airport in New York and a second point near Los Angeles International (LAX) in California. From these two points, we can build a line string which will then allow us to measure the geodesic distance between the two points. The query including the function definitions discussed above looks like this:</p>
<pre class="csharpcode">set hive.execution.engine=tez;

add jar wasb:<span class="rem">//gis@bluewaterdata.blob.core.windows.net/lib/esri-geometry-api.jar;</span>
add jar wasb:<span class="rem">//gis@bluewaterdata.blob.core.windows.net/lib/spatial-sdk-hadoop.jar;</span>

create temporary function ST_Point <span class="kwrd">as</span> <span class="str">'com.esri.hadoop.hive.ST_Point'</span>;
create temporary function ST_LineString <span class="kwrd">as</span> <span class="str">'com.esri.hadoop.hive.ST_LineString'</span>; 
create temporary function ST_GeodesicLengthWGS84 <span class="kwrd">as</span> <span class="str">'com.esri.hadoop.hive.ST_GeodesicLengthWGS84'</span>; 
create temporary function ST_SetSRID <span class="kwrd">as</span> <span class="str">'com.esri.hadoop.hive.ST_SetSRID'</span>; 

SELECT
    ST_GeodesicLengthWGS84(
        ST_SetSRID(
            ST_Linestring(40.773773, -73.872307, 33.944115, -118.40377),
            4326))/1000.0 * 0.62137119 AS DistanceInMiles;</pre>
<p><a href="https://bluewatersql.files.wordpress.com/2015/06/image.png"><img style="display: inline; border-width: 0;" title="image" src="https://bluewatersql.files.wordpress.com/2015/06/image_thumb.png" alt="image" width="741" height="399" border="0" /></a></p>
<h3>Building a Hive Geospatial Demo</h3>
<p>Now that I&rsquo;ve whet your appetite for the subject matter, let&rsquo;s turn our attention to building a more real-world demo beginning with the data. There are a number of examples floating around the interwebs that use a mythical set of Uber data. I say mythical because there are bigfoot like spotting of it but it appears as though the data set has been removed from the public domain and is no longer available. That being said a suitable substitute is the NYC Taxi Trip data made available by NYC Taxi Commission and Chris Whong via a FOIL request (read more about it and get the data <a href="https://chriswhong.com/open-data/foil_nyc_taxi/comment-page-2/" target="_blank">here</a>). This data set consists of two parts one with trip information (pick-up/drop-off date time and locations) and the second with fare and payment information. To build/run the demo below you will need to download the data from one of its many free sources and then upload it a blob storage account connected to your HDInsight cluster. Now spin up an appropriate sized cluster and let&rsquo; go. First let&rsquo;s create two external tables over top of the data file:</p>
<pre class="csharpcode">DROP TABLE IF EXISTS TABLE fares;
CREATE EXTERNAL TABLE fares (
medallion STRING,
hack_license STRING,
vendor_id STRING,
pickup_datetime STRING,
payment_type STRING,
fare_amount FLOAT,
surcharge FLOAT,
mta_tax FLOAT,
tip_amount FLOAT,
tolls_amount FLOAT,
total_amount FLOAT
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY <span class="str">','</span>
LINES TERMINATED BY <span class="str">'\n'</span>
STORED AS TEXTFILE
LOCATION <span class="str">'wasb://&lt;container&gt;@&lt;account&gt;.blob.core.windows.net/fares/'</span>
TBLPROPERTIES (<span class="str">"skip.header.line.count"</span>=<span class="str">"1"</span>);

DROP TABLE IF EXISTS trips;
CREATE EXTERNAL TABLE trips (
medallion STRING,
hack_license STRING,
vendor_id STRING,
rate_code STRING,
store_and_fwd_flag STRING,
pickup_datetime STRING,
dropoff_datetime STRING,
passenger_count INT,
trip_time_in_secs INT,
trip_distance FLOAT,
pickup_longitude STRING,
pickup_latitude STRING,
dropoff_longitude STRING,
dropoff_latitude STRING
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY <span class="str">','</span>
LINES TERMINATED BY <span class="str">'\n'</span>
STORED AS TEXTFILE
LOCATION <span class="str">'wasb://&lt;container&gt;@&lt;account&gt;.blob.core.windows.net/trips/'</span>
TBLPROPERTIES (<span class="str">"skip.header.line.count"</span>=<span class="str">"1"</span>);
</pre>
<p>Once the tables are in place, verify by issuing a few select statements using the LIMIT clause to verify that everything is primed and ready to go. With the set-up out of the way let&rsquo;s turn our attention to a use-case. The narrative for this demo is straight-forward: <em>The Contoso Taxi company is exploring new business opportunities and would like to analyze trips that either originated or terminated at La Guardia International Airport during the last year.</em>The primarily challenge as far as this post is concerned is indentifying which trips are in scope for the purpose of analysis. To start, the data for this time period is moderately substantial with about 2gb of data generated each month which makes using Hive beneficial since we can leverage it distributed nature for the purpose of processing. Complicating matters however it the trip data that only contains a latitude/longitude for both pickup and drop-off locations. So how can we go about solving this problem in Hive using the ESRI Geospatial UDFs? First, I used one of the many free mapping tools found on the interwebs to define a polygon that encapsulates La Guardia. This polygon is defined by a series of lat/long points and is represented in well-known text (WKT) format as seen below.</p>
<pre class="csharpcode">POLYGON ((40.773506 -73.889508, 40.774081 -73.884028, 40.779855 -73.884919, 
40.780605 -73.879043, 40.781755 -73.879373, 40.782805 -73.878614, 
40.78143 -73.87528, 40.786004 -73.871153, 40.785379 -73.869668, 
40.785079 -73.869734, 40.783705 -73.869304, 40.78233 -73.87046, 
40.782255 -73.871648, 40.78063 -73.872804, 40.772881 -73.856991, 
40.772355 -73.856661, 40.770381 -73.858081, 40.76753 -73.852666, 
40.765155 -73.851214, 40.764905 -73.851676, 40.767105 -73.853062, 
40.768781 -73.856694, 40.76703 -73.858707, 40.766805 -73.862768, 
40.770356 -73.867753, 40.771481 -73.870228, 40.771931 -73.872143, 
40.772031 -73.873893, 40.771755 -73.876236, 40.771256 -73.877887, 
40.770505 -73.87967, 40.769606 -73.881321, 40.76853 -73.8834, 
40.767756 -73.885513, 40.76723 -73.887428, 40.767105 -73.888055, 
40.773506 -73.889508))</pre>
<p>Using the shape data, I then can create a polygon object using the ST_Polygon UDF. Next, I use the ST_Point UDF to create a point for each trip&rsquo;s pickup and drop-off location. Finally, I use ST_Contains as a predicate to find trips that either begin or end within the polygon. The resulting abbreviated query looks as follows:</p>
<pre class="csharpcode">SELECT *
FROM trips
WHERE 
    ST_Contains(ST_Polygon(<span class="str">"&lt;OMITTED FROM BREVITY&gt;"</span>), ST_Point(pickup_longitude, pickup_latitude))
OR 
    ST_Contains(ST_Polygon(<span class="str">"&lt;OMITTED FROM BREVITY&gt;"</span>), ST_Point(dropoff_longitude, dropoff_latitude))</pre>
<p>Since we are interested in doing an analysis only on the trips identified, we would most like load these into a new table making whatever data transformations are needed in the process. The resulting full example including a new partitioned internal table and declarations is provided below.</p>
<pre class="csharpcode">DROP TABLE IF EXISTS nyc_taxi_analysis;

CREATE TABLE nyc_taxi_analysis (
    medallion STRING,
    hack_license STRING,
    vendor_id STRING,
    rate_code STRING,
    store_and_fwd_flag STRING,
    passenger_count INT,
    trip_time_in_secs INT,
    trip_distance FLOAT,
    pickup_longitude STRING,
    pickup_latitude STRING,
    dropoff_longitude STRING,
    dropoff_latitude STRING,
    trip_year INT, 
    trip_month INT, 
    trip_day INT
    trip_hour INT,
    trip_week INT,
    payment_type STRING,
    fare_amount FLOAT,
    surcharge FLOAT,
    mta_tax FLOAT,
    tip_amount FLOAT,
    tolls_amount FLOAT,
    total_amount FLOAT
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY <span class="str">','</span>
LINES TERMINATED BY <span class="str">'\n'</span>
STORED AS ORC;

set hive.execution.engine=tez;

add jar wasb:<span class="rem">//gis@bluewaterdata.blob.core.windows.net/lib/esri-geometry-api.jar;</span>
add jar wasb:<span class="rem">//gis@bluewaterdata.blob.core.windows.net/lib/spatial-sdk-hadoop.jar;</span>

create temporary function ST_Point <span class="kwrd">as</span> <span class="str">'com.esri.hadoop.hive.ST_Point'</span>;
create temporary function ST_Contains <span class="kwrd">as</span> <span class="str">'com.esri.hadoop.hive.ST_Contains'</span>;
create temporary function ST_Polygon <span class="kwrd">as</span> <span class="str">'com.esri.hadoop.hive.ST_Polygon'</span>;

INSERT OVERWRITE TABLE nyc_taxi_analysis PARTITION (year, month, day) 
SELECT
    t.medallion,
    t.hack_license,
    t.vendor_id,
    t.rate_code,
    t.store_and_fwd_flag,
    t.passenger_count,
    t.trip_time_in_secs,
    t.trip_distance,
    t.pickup_longitude,
    t.pickup_latitude,
    t.dropoff_longitude,
    t.dropoff_latitude,
    YEAR(t.pickup_datetime) AS trip_year,
    MONTH(t.pickup_datetime) AS trip_month,
    DAY(t.pickup_datetime) AS trip_day,
    HOUR(t.pickup_datetime) AS trip_hour,
    WEEKOFYEAR(t.pickup_datetime) AS trip_week,
    payment_type,
    fare_amount,
    surcharge,
    mta_tax,
    tip_amount,
    tolls_amount,
    total_amount
FROM Trips t
JOIN Fares f ON t.medallion = f.medallion
AND t.hack_license = f.hack_license
AND t.vendor_id = f.vendor_id
AND t.pickup_datetime = f.pickup_datetime
WHERE 
    ST_Contains(ST_Polygon(<span class="str">"POLYGON ((40.773506 -73.889508, 40.774081 -73.884028, 40.779855 -73.884919, 40.780605 -73.879043, 40.781755 -73.879373, 40.782805 -73.878614, 40.78143 -73.87528, 40.786004 -73.871153, 40.785379 -73.869668, 40.785079 -73.869734, 40.783705 -73.869304, 40.78233 -73.87046, 40.782255 -73.871648, 40.78063 -73.872804, 40.772881 -73.856991, 40.772355 -73.856661, 40.770381 -73.858081, 40.76753 -73.852666, 40.765155 -73.851214, 40.764905 -73.851676, 40.767105 -73.853062, 40.768781 -73.856694, 40.76703 -73.858707, 40.766805 -73.862768, 40.770356 -73.867753, 40.771481 -73.870228, 40.771931 -73.872143, 40.772031 -73.873893, 40.771755 -73.876236, 40.771256 -73.877887, 40.770505 -73.87967, 40.769606 -73.881321, 40.76853 -73.8834, 40.767756 -73.885513, 40.76723 -73.887428, 40.767105 -73.888055, 40.773506 -73.889508))"</span>), 
ST_Point(pickup_longitude, pickup_latitude))
OR 
    ST_Contains(ST_Polygon(<span class="str">"POLYGON ((40.773506 -73.889508, 40.774081 -73.884028, 40.779855 -73.884919, 40.780605 -73.879043, 40.781755 -73.879373, 40.782805 -73.878614, 40.78143 -73.87528, 40.786004 -73.871153, 40.785379 -73.869668, 40.785079 -73.869734, 40.783705 -73.869304, 40.78233 -73.87046, 40.782255 -73.871648, 40.78063 -73.872804, 40.772881 -73.856991, 40.772355 -73.856661, 40.770381 -73.858081, 40.76753 -73.852666, 40.765155 -73.851214, 40.764905 -73.851676, 40.767105 -73.853062, 40.768781 -73.856694, 40.76703 -73.858707, 40.766805 -73.862768, 40.770356 -73.867753, 40.771481 -73.870228, 40.771931 -73.872143, 40.772031 -73.873893, 40.771755 -73.876236, 40.771256 -73.877887, 40.770505 -73.87967, 40.769606 -73.881321, 40.76853 -73.8834, 40.767756 -73.885513, 40.76723 -73.887428, 40.767105 -73.888055, 40.773506 -73.889508))"</span>), 
ST_Point(dropoff_longitude, dropoff_latitude));</pre>
<p>Running the above script on a 16-node cluster and it completed in 638 seconds (your results may vary). Query the results to sample/review and ensure everything is in order.</p>
<h3>Wrap-Up</h3>
<p>In this post I introduced the ESRI Geospatial UDF library and the steps needed to run in on a HDInsight cluster. I discussed building a demo on real-world data to highlight a portion of the capabilities these functions provide. I hope you were able to take away at least a high level overview of the geospatial capabilities available within Hive and that should the need arise in a future project you can leverage these capabilities as appropriate. Till next time!</p>
<h1>Chris</h1>]]></content:encoded>
    </item>
    <item>
      <title>Automating Update of Azure-Powershell</title>
      <link>https://docs.microsoft.com/archive/blogs/bluewatersql/automating-update-of-azure-powershell</link>
      <pubDate>Thu, 28 May 2015 08:40:18 GMT</pubDate>
      <dc:creator><![CDATA[Bluewater SQL]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/bluewatersql/2015/05/28/automating-update-of-azure-powershell/</guid>
      <description><![CDATA[Just a quick post to share a useful script. The PowerShell script below will download and update the...]]></description>
      <content:encoded><![CDATA[<p>Just a quick post to share a useful script. The PowerShell script below will download and update the Azure-PowerShell command-lets to the latest and greatest version. It even does a slick little version compare. I&rsquo;ll put the disclaimer out there, that I an not the original author of this script and unfortunately I&rsquo;ve lost the reference. If this is your script or you have a link to the original author&rsquo;s blog post, pass it along and I&rsquo;ll be happy to give credit where it is due. At any rate, the script is below:</p>
<pre class="csharpcode">$AzureModule = Get-Module -Name Azure -ListAvailable
$LatestRelease = Invoke-RestMethod 
    -Uri https:<span class="rem">//api.github.com/repos/Azure/azure-powershell/releases/latest -Method GET</span>

If ($AzureModule.Version.ToString() -ne $LatestRelease.name)
{
    $OutFile = <span class="str">"{0}\{1}"</span> -f $env:TEMP, $LatestRelease.assets.name
    Invoke-WebRequest -Uri $LatestRelease.assets.browser_download_url -OutFile $Outfile -Method Get
    Start-Process -FilePath msiexec.exe -ArgumentList @(<span class="str">"/i $OutFile /qb"</span>) -Wait -PassThru
}
<span class="kwrd">else</span>
{
    Write-Host <span class="str">"Azure Powershell module is up to date."</span>

}
</pre>
<p>Till next time! Chris</p>]]></content:encoded>
    </item>
    <item>
      <title>Building an Azure ML SSIS Task</title>
      <link>https://docs.microsoft.com/archive/blogs/bluewatersql/building-an-azure-ml-ssis-task</link>
      <pubDate>Sat, 04 Apr 2015 13:16:00 GMT</pubDate>
      <dc:creator><![CDATA[Bluewater SQL]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/bluewatersql/2015/04/04/building-an-azure-ml-ssis-task/</guid>
      <description><![CDATA[In several previous blog posts (HERE and HERE), I&rsquo;ve introduced and discussed the Azure...]]></description>
      <content:encoded><![CDATA[<p>In several previous blog posts (<a title="Azure Machine Learning &ndash; First Look" href="https://bluewatersql.wordpress.com/2014/07/31/azure-machine-learning-first-look/">HERE</a> and <a title="Azure Machine Learning &ndash; A Deeper Look" href="https://bluewatersql.wordpress.com/2014/08/01/azure-machine-learning-a-deeper-look/">HERE</a>), I&rsquo;ve introduced and discussed the Azure Machine Learning service, its features, benefits and general capabilities. Since that time I have been toying with the idea of a building a custom SSIS Task to integrate Azure ML into SSIS.</p>
<p>My vision of the project is pretty simple and is roughly modeled after the built-in Execute SQL and Web Service Tasks. First, since the Azure ML batch execution service requires the input data to be hosted in an Azure Blob Storage account, the task would be capable of either uploading the required input data to an Azure Blob Storage account or simply using an URI to an existing blob. If the input source is not an existing blob, that data could come from a variable, a file connection or via direct input.</p>
<p>Next, the task would execute and monitor the batch prediction job via the end point provided. The task would also periodically log the status for the purpose of visibility. When the job completes, the task would allow the results to be downloaded to either a string variable or file connection.</p>
<p>To start, I re-purposed the Azure Storage Connection Manager found in <a href="https://code.msdn.microsoft.com/windowsazure/Azure-Blob-Storage-fc25adbf" target="_blank">SSIS Azure Blob Storage sample project</a> on MSDN. The project itself consists of just a single task which I called ExecuteAzureMLBatch and its supporting classes. While a deep dive into the code is outside the scope of this post, those that are interested can download the project directly from my Github project: <a title="https://github.com/bluewatersql/AzureMLSSIS" href="https://github.com/bluewatersql/AzureMLSSIS">https://github.com/bluewatersql/AzureMLSSIS</a>.</p>
<h3>Building the ExecureAzureMLBatch Task</h3>
<p>1. Download the code from <a title="https://github.com/bluewatersql/AzureMLSSIS" href="https://github.com/bluewatersql/AzureMLSSIS">https://github.com/bluewatersql/AzureMLSSIS</a></p>
<p>2. The solution consists of two projects: one for the connection manager and one for the task itself. The build events for both projects handle all the heavy lifting for using the components on your location machine. Ensure the path to GacUtil.exe as well as your SQL Server installation found in the Post-Build Events is correct for your machine. Note that you need to do this for both projects.</p>
<p><a href="https://bluewatersql.files.wordpress.com/2015/04/image.png"><img style="border-width: 0px; display: inline;" title="image" src="https://bluewatersql.files.wordpress.com/2015/04/image_thumb.png" alt="image" width="473" height="272" border="0" /></a></p>
<p>3. Build the project. The post-build events discussed in step 2 take care of registering the required assemblies in the GAC and copying the files to the required directories. If you get any squirrely errors, you may need to run Visual Studio as an Administrator to successful run GacUtil.</p>
<h3>Using the ExecuteAzureMLBatch Task</h3>
<p>After the solution has been successful built, your ready to use the task in an SSIS package. To use the task successfully, use the following steps:</p>
<ol>
<li>Add a new Windows Azure Storage connection manager to your package. This connection does not have a design-time UI for configuration so you will need to use the properties window to set the following properties for where experiment sample data will live:</li>
<ul>
<li>UseDevelopmentStorage = false</li>
<li>StorageName = &lt;STORAGE_ACCOUNT /&gt;</li>
<li>AccessKey = &lt;STORAGE_ACCOUNT_ACCESS_KEY /&gt;</li>
<li>Path = &lt;CONTAINER_NAME /</li>
</ul>
<li>Add the ExecuteAzureML task to the control flow design surface and configure.
<ul>
<li>Set the Azure ML Batch URL Endpoint (ex: https://ussouthcentral.services.azureml.net/workspaces/&lt;&hellip;.&gt;/services/&lt;&hellip;&gt;/jobs)</li>
<li>Set the Azure ML Key</li>
<li>The experiment input source can come from a variable, a file connection or by direct input.</li>
<li>The experiment destination can be none, variable or a file connection and determines where the results are loaded to. Note that when none is specified the results are not downloaded.</li>
<li><a href="https://bluewatersql.files.wordpress.com/2015/04/image1.png"><img style="border-width: 0px; display: inline;" title="image" src="https://bluewatersql.files.wordpress.com/2015/04/image_thumb1.png" alt="image" width="421" height="401" border="0" /></a></li>
</ul>
</li>
<li>Run your package</li>
</ol>
<p><a href="https://bluewatersql.files.wordpress.com/2015/04/image2.png"><img style="border-width: 0px; display: inline;" title="image" src="https://bluewatersql.files.wordpress.com/2015/04/image_thumb2.png" alt="image" width="616" height="386" border="0" /></a></p>
<p>Once the rask runs, you can process the results as required. I hope you find this as interesting as I do and feel free to let me know if you have suggestions, feedback or would like to actively contribute.</p>
<p>Till next time!</p>
<h1>Chris</h1>]]></content:encoded>
    </item>
    <item>
      <title>Ooooh I'm Telling: Doing Swear Word Analysis with Storm on HDInsight</title>
      <link>https://docs.microsoft.com/archive/blogs/bluewatersql/ooooh-im-telling-doing-swear-word-analysis-with-storm-on-hdinsight</link>
      <pubDate>Wed, 25 Feb 2015 13:12:00 GMT</pubDate>
      <dc:creator><![CDATA[Bluewater SQL]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/bluewatersql/2015/02/25/ooooh-im-telling-doing-swear-word-analysis-with-storm-on-hdinsight/</guid>
      <description><![CDATA[As promised, this is the first of three (maybe more) posts that will present an end-to-end example...]]></description>
      <content:encoded><![CDATA[<p>As promised, this is the first of three (maybe more) posts that will present an end-to-end example to showcase the distributed streaming capabilities of the Apache Storm project. This first post will provide an introduction to the project and an overview of all the moving pieces.</p>
<p>Please note that I will not be getting into line-by-line code examples outside of those that are relevant to the Storm deployment. Likewise, I will not get too deep into any of the peripheral technologies involved. I will leave those for either a later blog post or an exercise for you the reader. The complete project and source will be posted to GitHub (<a href="https://github.com/bluewatersql/Storm">HERE</a>).</p>
<p>The rationale for this project is pretty straight-forward. As a father to young kids, I became acutely aware of swear words and foul language when my kids reach the parroting stage. For those without kids, this is the stage where a two or three year old hears a word and randomly begins inserting it into their daily vocabulary (typically at the most inopportune times, like when mom is around). This offers many humorous and potentially embarrassing moments depending on the environment.</p>
<p>To play off of this and since Twitter is useful for all sorts of things beyond letting people know what you are doing minute by minute, I decided to do some seemingly simple swear word analysis on people&rsquo;s tweets. This analysis would hopefully allow me to answer questions like:</p>
<ul>
<li>Which parts of the world have the worst potty mouths?</li>
<li>In what context (sentiment) do people use swear words?</li>
<li>Can I identify topics or hashtags that people curse about the most?</li>
<li>Who are the top 10 worst potty mouths on Twitter?</li>
</ul>
<p>Luckily, all of these question can be easily answered and since it would be nice to do it in real-time, Apache Storm is perfectly suited to the task given the volume and velocity of data in the Twitter stream.</p>
<h3>Project Overview</h3>
<p>The bulk of this demonstration project, which I will refer to as Twitter Tattletale revolves around common ETL types of activities you would expect to find in a non-streaming, traditional BI/batch processing solution. In fact for this pseudo phase one implementation I will ignore streaming analytics entirely (and a fancy, pretty UI) so we can even break it down into ETL steps. Please understand, that even though I am comparing this to a more traditional ETL process, these steps occur in an unbounded manner, meaning that instead of a fixed beginning and end like that of a SSIS of Hadoop job they run continuously until terminated.</p>
<h4>Extract</h4>
<p>The entry point for this project is an Azure Service Bus queue. An external application handles consuming the Twitter stream and publishing brokered messages to the queue so our solution will simply need to ingest these messages.</p>
<h4>Transform</h4>
<p>There are multiple cleaning, filtering, enrichment and transformation steps that occur within this project. The process starts by filtering tweets so that only those in English are processed. Next, external services are used to determine the tweet&rsquo;s sentiment and to reverse geocode the location based on the latitude and longitude coordinates if provided. Then, the tweet text is split into words for cleaning and indexing. Noise words, special characters, user mentions and urls are all stripped away before determining if the tweet is vulgar by counting the instance/number of swear words.</p>
<h4>Load</h4>
<p>Rather than loading a dimensional data warehouse, the tattletale project stores data in multiple formats each with its own purpose. Raw tweet data is stored so that it can be process later in a more traditional batch process such as with HDInsight (Hadoop). Aggregated data from the stream is persisted for both the tweet and extracted topics in a database (HBase). Now that the work has been defined, let&rsquo;s move on.</p>
<h3>Technologies and Considerations</h3>
<p>There are some miscellaneous pieces that are ultimately external to Apache Storm but are important nonetheless. First, is the event producer which is responsible for capturing and storing tweets to the Service Bus queue. The application uses the <a href="https://tweetinvi.codeplex.com/" target="_blank">Tweetinvi</a> API to capture streaming tweets. For the demo I have implemented this as an Azure Worker Role, though it couple be easily run as a console based application on your desktop. The important thing to remember is that this event producer could ultimately be anything and the source of the stream could come from virtually anywhere. Next is <a href="https://hbase.apache.org/" target="_blank">Apache HBase</a>. HBase is a distributed NoSQL database built on top of HDFS and based largely on Google Big Table. It is a columnar database, optimized for high volume, high velocity real-time random red/write access. Whew&hellip;that was a mouth full. Please note that the database you choose does not matter to Apache Storm. Outside of demo-land your choice should be driven by the requirements of whatever it is you are trying to build and implement.</p>
<h3>SCP.Net</h3>
<p>Now on to the good stuff. Before discussing the project specific topology, it is necessary to introduce <a href="https://azure.microsoft.com/en-us/documentation/articles/hdinsight-hadoop-storm-scpdotnet-csharp-develop-streaming-data-processing-application/" target="_blank">SCP.Net (Stream Computing Platform)</a>. Storm, like most Apache projects is largely Java centric. Most of the documentation and/or examples that you&rsquo;ll run across are written in either Java or Python. This abstraction allows you to build a Storm topology and deploy it a HDInsight Storm cluster either purely in .Net or in a hybrid deployment using a mix of Java and .Net. The link referenced above does a good job of explaining SCP.Net in greater detail and you can get started using it by installing HDInsight tools for Visual Studio in the authors follow-up <a href="https://azure.microsoft.com/en-us/documentation/articles/hdinsight-hadoop-storm-scpdotnet-csharp-develop-streaming-data-processing-application/" target="_blank">post</a>.</p>
<h3>The Twitter Tattletale Topology</h3>
<p>Recalling from the prior post that a Storm Topology consists of streams, spouts and bolts. Let&rsquo;s start with a picture (below) and then take a look at each piece of the topology for the Twitter Tattletale demo. <a href="https://bluewatersql.files.wordpress.com/2015/02/topology.png"><img style="display: inline; border-width: 0;" title="Topology" src="https://bluewatersql.files.wordpress.com/2015/02/topology_thumb.png" alt="Topology" width="670" height="466" border="0" /></a></p>
<ol>
<li>Topology &ndash; the topology is a simple non-transactional topology, meaning that we do not necessarily care that data is processed in the order it was received.</li>
<li>Twitter Spout - reads brokered messages from the Azure Service Bus queue. The brokered messages consist on tweets serialized as JSON. The spout extracts the unique tweet id and tweet language and then filters out non-English tweets before emitting a tuple into the data stream. The tuple consists of the unique id and tweet JSON. Note that in an ideal (read non-demo) situation, the spout would be more generic than it is. The business of filtering should be done in a bolt, so that the spout could be potentially reused by other topologies.</li>
<li>Blob Writer Bolt &ndash; as the name implies, this bolt runs independent of the primary processing stream to write raw tweets (JSON) to a configured container in a Azure Blob Storage account. The bolt writes one blob per tweet using blob delimiters to annotate year, month and day of the tweet so the data set can be easily partitioned in Hive for later processing. I intentionally did not perform any aggregation meaning you would potentially wind up with millions of 1k files. This is not ideal for Hadoop batch processing. A batch process could be added to handle this and any compression (gzip/lzo).</li>
<li>Sentiment Bolt &ndash; calls an external REST-based service to determine the tweet&rsquo;s sentiment. Currently the bolt uses the <a href="https://www.sentiment140.com/" target="_blank">Sentiment140</a> API to classify each tweet as positive, negative or neutral. In the future (i.e. when I have time), I will leverage an AzureML service. The sentiment bolt emits a new tuple that consist of the unique id, serialized tweet and sentiment.</li>
<li>Geography Bolt &ndash; calls the Bing Maps API location service to reverse geo-code a tweets location when a latitude and longitude are provided. The Bing Maps API returns AdminDistrict, AdminDistrict2, CountryRegion, Locality and PostalCode all of which are emitted with the unique tweet id in a new data stream.</li>
<li>Merge Bolt &ndash; unions or joins the split processing workflow back into a single unified workflow. Since the sentiment and geography bolts both depend on external services, the decision was made to perform both operations in parallel. The merge bolt use field grouping on the unique tweet id to ensure that tuples with same id are routed to same worker.</li>
<li>Swear Word Bolt &ndash; handles most of the heavy lifting for this streaming process. This bolt prepares tweets by stripping out special characters, emojiis, urls and user mentions before splitting the tweet into unigrams and bigrams. Noise words are removed and a swear word dictionary identifies and counts all swear words. Two data streams are emitted from this bolt: tweets and topics.</li>
<li>HBase Tweet Bolt &ndash; writes enriched tweets to a HBase tweets table. Internally it uses an queue to implement micro-batching that is trigger by either batch size or a system tick tuple that is fired by Storm at a configured interval. The decision to micro-batch writes was made due to the fact that the C# HBase API is implement using the HBASE REST API (formerly Stargate).</li>
<li>HBase Topic Bolt &ndash; writes tweet topics with both sentiment, geography and a flag to indicate if swear words where found within the tweet context. Like the HBase Tweet Bolt this bolt also implements the micro-batching pattern, rather than individual writes.</li>
</ol>
<h3>Running the Demo</h3>
<p>Since the demo consist of multiple pieces, there are prerequisites that have to be satisfied before running the Storm topology.</p>
<ol>
<li>Azure Storage Accounts need to be created for the various Azure services used.</li>
<li>An Azure Service Bus namespace needs to be defined and a Queue to hold the tweets created.</li>
<li>A Cloud Service needs to be provisioned and the application which captures the Twitter stream should be deployed as a Worker Role.</li>
<li>Provision a HDInsight HBase cluster and Remote Desktop needs to be enabled if you want to use the HBase Shell to issue queries.</li>
<li>Provision a HDInsight Storm cluster</li>
</ol>
<p>You probably noticed that I left out compute or sizing specifications for some of the prerequisites. This is intentional since how much &ldquo;horsepower&rdquo; you need depends on what you are trying to do with the demo and we will discuss scaling in a later post. After the prerequisites are in place, your topology can be deployed directly from Visual Studio using HDInsight Tools (&lsquo;Submit to Storm on HDInsight&rsquo; found on the project context menu). The add-in connects to your Azure account, finds your Storm cluster, builds the topology spec file (based on the TopologyDescriptor class marked as active), zips up the required files and finally deploys everything to the cluster.</p>
<table style="width: 800px;" border="0" cellspacing="0" cellpadding="2">
<tbody>
<tr>
<td valign="top" width="400"><a href="https://bluewatersql.files.wordpress.com/2015/02/image7.png"><img style="display: inline; border-width: 0;" title="image" src="https://bluewatersql.files.wordpress.com/2015/02/image_thumb7.png" alt="image" width="395" height="126" border="0" /></a></td>
</tr>
<tr>
<td valign="top" width="400"><a href="https://bluewatersql.files.wordpress.com/2015/02/image8.png"><img style="display: inline; border-width: 0;" title="image" src="https://bluewatersql.files.wordpress.com/2015/02/image_thumb8.png" alt="image" width="400" height="105" border="0" /></a></td>
</tr>
</tbody>
</table>
<p>One the topology has been submitted and is running, you can monitor it from the Storm Dashboard found in the <a href="https://manage.windowsazure.com" target="_blank">Azure Portal</a>or by using the Storm Topology Viewer in Visual Studio.</p>
<table style="width: 800px;" border="0" cellspacing="0" cellpadding="2">
<tbody>
<tr>
<td valign="top" width="400"><a href="https://bluewatersql.files.wordpress.com/2015/02/image9.png"><img style="display: inline; border-width: 0;" title="image" src="https://bluewatersql.files.wordpress.com/2015/02/image_thumb9.png" alt="image" width="387" height="372" border="0" /></a></td>
</tr>
<tr>
<td valign="top" width="400"><a href="https://bluewatersql.files.wordpress.com/2015/02/image10.png"><img style="display: inline; border-width: 0;" title="image" src="https://bluewatersql.files.wordpress.com/2015/02/image_thumb10.png" alt="image" width="402" height="205" border="0" /></a></td>
</tr>
</tbody>
</table>
<p>To see what Twitter Tattletale is actually doing, you can query HBase using the HBase shell, an HBase API or by using Hive. Creating a Hive table over HBase is by far the easiest approach (although least performant approach). The script below will create two Hive tables: one for tweets and one for topics.</p>
<pre class="csharpcode">DROP TABLE IF EXISTS hbase_tweets;
CREATE EXTERNAL TABLE hbase_tweets(
rowkey <span class="kwrd">string</span>, screenname <span class="kwrd">string</span>, country <span class="kwrd">string</span>, created_date <span class="kwrd">string</span>, sentiment <span class="kwrd">string</span>, swearwords <span class="kwrd">int</span>)
STORED BY <span class="str">'org.apache.hadoop.hive.hbase.HBaseStorageHandler'</span>
WITH SERDEPROPERTIES (
<span class="str">'hbase.columns.mapping'</span> = <span class="str">':key,user:screenname,loc:country_region,tweet:created_dt, tweet:sentiment,tweet:swear_word_count'</span>)
TBLPROPERTIES (<span class="str">'hbase.table.name'</span> = <span class="str">'tweets'</span>);

DROP TABLE IF EXISTS hbase_topics;
CREATE EXTERNAL TABLE hbase_topics(
rowkey <span class="kwrd">string</span>, country <span class="kwrd">string</span>, created_date <span class="kwrd">string</span>, sentiment <span class="kwrd">string</span>, vulgar_tweet boolean)
STORED BY <span class="str">'org.apache.hadoop.hive.hbase.HBaseStorageHandler'</span>
WITH SERDEPROPERTIES (
<span class="str">'hbase.columns.mapping'</span> = <span class="str">':key,tp:country_region,tp:created_dt,tp:sentiment,tp:vulgar_tweet'</span>)
TBLPROPERTIES (<span class="str">'hbase.table.name'</span> = <span class="str">'topics'</span>);</pre>
<p>We can now query the tables to browse the data being collected, scrubbed and enriched using simple Hive queries.</p>
<table style="width: 800px;" border="0" cellspacing="0" cellpadding="2">
<tbody>
<tr>
<td valign="top" width="450">
<pre style="height: 222px; width: 494px;">--Summarize tweets by country
SELECT
    COUNT(*) AS TotalTweets,
    SUM(IF(swearwords &gt; 0, 1, 0)) AS VulgarTweets,
    SUM(swearwords) AS TotalSwearWords,
    country
FROM hbase_tweets
WHERE country IS NOT NULL
GROUP BY country
ORDER BY VulgarTweets DESC;</pre>
</td>
</tr>
<tr>
<td valign="top" width="350"><a href="https://bluewatersql.files.wordpress.com/2015/02/snaghtml14a7ea8b.png"><img style="display: inline; border-width: 0;" title="SNAGHTML14a7ea8b" src="https://bluewatersql.files.wordpress.com/2015/02/snaghtml14a7ea8b_thumb.png" alt="SNAGHTML14a7ea8b" width="297" height="251" border="0" /></a></td>
</tr>
<tr>
<td valign="top" width="450">
<pre style="height: 220px; width: 494px;">--Top 15 negative bigrams by country
SELECT
    SPLIT(rowkey,<span class="str">'[_]'</span>)[0] AS key,
    country,
    COUNT(*) AS TopicCount
FROM hbase_topics
WHERE sentiment=<span class="str">'Negative'</span>
AND SIZE(SPLIT(SPLIT(rowkey,<span class="str">'[_]'</span>)[0],<span class="str">'[ ]'</span>)) &gt; 1
GROUP BY SPLIT(rowkey,<span class="str">'[_]'</span>)[0], country
ORDER BY TopicCount DESC;</pre>
</td>
</tr>
<tr>
<td valign="top" width="350"><a href="https://bluewatersql.files.wordpress.com/2015/02/snaghtml14b6d3ae.png"><img style="display: inline; border-width: 0;" title="SNAGHTML14b6d3ae" src="https://bluewatersql.files.wordpress.com/2015/02/snaghtml14b6d3ae_thumb.png" alt="SNAGHTML14b6d3ae" width="240" height="217" border="0" /></a></td>
</tr>
<tr>
<td valign="top" width="450">
<pre class="csharpcode" style="height: 199px; width: 576px;">--XBox tweets by country
SELECT
    country,
    COUNT(*) AS TopicCount
FROM hbase_topics
WHERE SPLIT(rowkey,<span class="str">'[_]'</span>)[0] = <span class="str">'xbox'</span>
GROUP BY country
ORDER BY TopicCount DESC
LIMIT 15;</pre>
</td>
</tr>
<tr>
<td valign="top" width="350"><a href="https://bluewatersql.files.wordpress.com/2015/02/snaghtml14c399f2.png"><img style="display: inline; border: 0;" title="SNAGHTML14c399f2" src="https://bluewatersql.files.wordpress.com/2015/02/snaghtml14c399f2_thumb.png" alt="SNAGHTML14c399f2" width="240" height="115" border="0" /></a></td>
</tr>
</tbody>
</table>
<h3>Credits</h3>
<p>Before I wrap-up, I need to give credit where credit is due: <a href="https://azure.microsoft.com/en-us/documentation/articles/hdinsight-hbase-analyze-twitter-sentiment/" target="_blank">Analyzing real-time Twitter sentiment with HBase in HDInsight</a></p>
<h3>Wrap-Up</h3>
<p>In this post, I introduce the basis and topology for the my Storm demonstration project: Twitter Tattletale. Although the subject matter of the demo is meant to be light-hearted and humorous the goal of this post (and the next few) is to introduce you to this very powerful and flexible Azure offering that presents new options for handle real-time streaming data in a distributed processing environment .In my next post, we will dig into the code, talk testing and finally deployment. Till next time! &nbsp;</p>
<h1>Chris</h1>]]></content:encoded>
    </item>
    <item>
      <title>Introduction to Apache Storm</title>
      <link>https://docs.microsoft.com/archive/blogs/bluewatersql/introduction-to-apache-storm</link>
      <pubDate>Mon, 23 Feb 2015 19:36:00 GMT</pubDate>
      <dc:creator><![CDATA[Bluewater SQL]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/bluewatersql/2015/02/23/introduction-to-apache-storm/</guid>
      <description><![CDATA[The Apache Storm&nbsp;project delivers a platform for real-time distributed (complex event)...]]></description>
      <content:encoded><![CDATA[<p>The <a href="https://storm.apache.org/" target="_blank">Apache Storm</a>&nbsp;project delivers a platform for real-time distributed (complex event) processing across extremely large volume, high velocity data sets. By providing a simple, easy-to-use abstraction, Storm enables real-time analytics, online machine learning and operational/ETL scenarios that have previously been non-trivial to implement. In this post we will familiarize ourselves with the Storm platform, its architecture and the terminology you need to be successful. This post sets the stage form a new blog series that will jog through creating a real-time ETL project based on Storm.</p>
<h3>History &amp; Storm Use Cases</h3>
<p><a href="https://storm.apache.org/" target="_blank">Apache Storm</a>&nbsp;was originally developed by Nathan Marz and the BackType team. BackType was later acquired by Twitter, who open-sourced the project. Storm is designed to be fast (benchmarked at 1 million 100 byte messages per second per node on commodity hardware), scalable and reliable with unbounded streaming data. It is also easy to use as it supports a number of different programming languages (Java, Python, Ruby, JavaScript and C#). These characteristic make it a perfect platform for handling distributed real-time event processing. Some of the most common real-time processing scenarios currently in place are:</p>
<ol>
<li>Financial fraud detection</li>
<li>Network outage and/or intrusion detection</li>
<li>Preventative maintenance in manufacturing and transportation</li>
<li>Application monitoring</li>
<li>Customization or personalization of web content</li>
</ol>
<h3>Architecture</h3>
<p>An Apache Storm architecture follows a master/slave architecture in a manner similar to Hadoop. The architecture consists of three different types of nodes who all function in different roles to deliver at-least once guaranteed message processing (exactly once message processing is also support through an abstract called <a href="https://storm.apache.org/documentation/Trident-tutorial.html" target="_blank">Trident</a>).</p>
<p><a href="https://bluewatersql.files.wordpress.com/2015/02/drawing1.jpg"><img style="display: inline; border: 0;" title="Drawing1" src="https://bluewatersql.files.wordpress.com/2015/02/drawing1_thumb.jpg" alt="Drawing1" width="453" height="261" border="0" /></a></p>
<p>These nodes are:</p>
<ul>
<li>Nimbus (the master node) &ndash; a single daemon processes responsible for deploying, managing, coordinating and monitoring topologies running on the cluster. The master node assigns or reassigns all work when failures occur and is also responsible for distributing any required files to the supervisor nodes</li>
<li><a href="https://zookeeper.apache.org/" target="_blank">ZooKeepers</a> &ndash; In a distributed environment, centralized event and information coordinate is critical to processes coordination. Apache ZooKeeper functions in this role within the architecture, storing state information such as work assignments and job status between Nimbus and Supervisor nodes.</li>
<li>Supervisors (the worker nodes) &ndash; a daemon processes that spawn new task and monitor the status of workers. When Nimbus assigns a task to a Supervisor, the Supervisor spawns a new JVM process to execute each job.</li>
</ul>
<h3>Terminology</h3>
<p>Getting started with Storm requires that you familiarize yourself with the terminology you&rsquo;ll encounter as you begin building a distributed streaming processing solution.</p>
<h6>Topologies</h6>
<p>Analogous to a job, such as those found in more traditional or batch processing systems. Topologies are made up of data streams, spouts and bolts and are deployed to and run by an Apache Storm cluster. Topologies can be either defined as transactional (strictly defined order of events) or non-transactional and run indefinitely.</p>
<h6>Data Streams</h6>
<p>An unbound stream of tuples (a collection of key/value pairs), which serve as the most basic data structure within storm.</p>
<h6>Spouts</h6>
<p>The entry point into a Storm topology. A spout connects to a source of data, such as a database or a service bus event queue, transforms the data into a tuple and then emits the tuple for consumption and processing by one or more bolts.</p>
<h6>Bolts</h6>
<p>Responsible for transforming and processing data within your topology. Bolts can receive one or more data streams as inputs from spouts or even other bolts and can produce zero, one or more data streams as output. Common activities within bolts are calculations, filtering, aggregations, joins and writes to external sources such as a traditional relational or no-sql databse or even trigger a connected application event through web sockets or SignalR. When taken together these pieces allow you to easily implement a range of real-time processing systems. For example, suppose we captured tweets or Twitter messages and stored them on a Service Bus queue. A simple topology would start with a spout reading the tweets from the queue and emitting them for processing as tuples into the data stream. Subsequent bolts could be used to store the raw tweet to Azure Blob Storage for later consumption by a Hadoop cluster, while a second bolt could add value to the tweets by determining the tweet&rsquo;s sentiment. Aggregation could be done on some arbitrary field such as hashtag or location. That aggregated level of data could then be pushed to an HBase database as well as a real-time dashboard built using SignalR. A visual repesentation of the previously describe topology is seen below.</p>
<p><a href="https://bluewatersql.files.wordpress.com/2015/02/drawing11.jpg"><img style="display: inline; border: 0;" title="Drawing1" src="https://bluewatersql.files.wordpress.com/2015/02/drawing1_thumb1.jpg" alt="Drawing1" width="503" height="190" border="0" /></a></p>
<h3>Getting Started</h3>
<p>So you&rsquo;ve made it through the overview and your itching to get started, but noticed that I never discussed what it takes to set-up a Storm cluster. Rather than an inadvertent oversight this was deliberate since Storm clusters can be easily provisioned as a service within Microsoft Azure. If you are familiar with provisioning an HDInsight cluster, the process is nearly identical. For those that are not familiar with Hadoop, you will find the Storm option under the Data Services and HDInsight within the add menu as seen below. Using the quick create, you can specify a cluster name, size, subscription, storage account and an admin password and be off an running. <a href="https://bluewatersql.files.wordpress.com/2015/02/image6.png"><img style="display: inline; border: 0;" title="image" src="https://bluewatersql.files.wordpress.com/2015/02/image_thumb6.png" alt="image" width="512" height="246" border="0" /></a></p>
<h3>Wrap-Up</h3>
<p>This post was foundational as we introduced Apache Storm. We reviewed the basic architecture and discussed common terminology you need to know to get started. Over the next couple of posts we will look at the steps necessary to build and deploy an example topology using C#. Till next time!</p>
<h1>Chris</h1>]]></content:encoded>
    </item>
    <item>
      <title>Something's Brewing with Azure Data Factory - Part 3</title>
      <link>https://docs.microsoft.com/archive/blogs/bluewatersql/somethings-brewing-with-azure-data-factory-part-3</link>
      <pubDate>Wed, 04 Feb 2015 08:45:23 GMT</pubDate>
      <dc:creator><![CDATA[Bluewater SQL]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/bluewatersql/2015/02/04/somethings-brewing-with-azure-data-factory-part-3/</guid>
      <description><![CDATA[In the first two parts of this blog series (HERE and HERE), we used Azure Data Factory to load Beer...]]></description>
      <content:encoded><![CDATA[<p>In the first two parts of this blog series (<a title="Something&rsquo;s Brewing with Azure Data Factory" href="https://bluewatersql.wordpress.com/2015/01/27/somethings-brewing-with-azure-data-factory/">HERE</a> and <a title="Something&rsquo;s Brewing with Azure Data Factory Part 2" href="https://bluewatersql.wordpress.com/2015/02/02/somethings-brewing-with-azure-data-factory-part-2/">HERE</a>), we used Azure Data Factory to load Beer review data from an Azure SQL Database to an Azure Blob Storage account. We then processed that data using HDInsight and the Mahout Machine Learning Library to generate user-based recommendations. In this final post, we will take those recommendations and massage them back into our Azure SQL Database where they can be consumed by users.</p>
<h3>The Set-Up</h3>
<p>The output of the Mahout MapReduce job is a file of recommendations in a pivoted format. The format of the file is as follows which each user represented on a single line:</p>
<pre class="csharpcode">{USERID}    [{BEERID}:{ESTIMATEDRATING},{BEERID}:{ESTIMATEDRATING},{BEERID}:{ESTIMATEDRATING},....]</pre>
<p>In order to make use of these recommendations we need to unpivot the data such that each user/beer recommendation is on a single line in comma-separated value (CSV) format. To do this we will use a couple of iterations of Hive queries to transform and filter the recommendations before loading.</p>
<h3>Creating the Hive Job</h3>
<p>The transformation of the Mahout generated recommendations into a CSV file occurs in four steps. I have documented the steps below but will leave the detail explanation of how Hive queries work for some other time.</p>
<h5>Step 1 - Create a Hive table over-top of the Mahout output</h5>
<pre class="csharpcode"><span class="kwrd">DROP</span> <span class="kwrd">TABLE</span> <span class="kwrd">IF</span> <span class="kwrd">EXISTS</span> RecommendationsRaw;
<span class="kwrd">CREATE</span> <span class="kwrd">EXTERNAL</span> <span class="kwrd">TABLE</span> RecommendationsRaw (
    USERID <span class="kwrd">INT</span>,
    RECOMMENDATIONS STRING
)
<span class="kwrd">ROW</span> FORMAT DELIMITED FIELDS TERMINATED <span class="kwrd">BY</span> <span class="str">'\t'</span>
LINES TERMINATED <span class="kwrd">BY</span> <span class="str">'\n'</span>
LOCATION <span class="str">'${hiveconf:MahoutInput}'</span>;</pre>
<h5>Step 2 - Strip the square-brackets (&lsquo;[&lsquo; and &lsquo;]&rsquo;) and load data into a clean staging table</h5>
<pre class="csharpcode"><span class="kwrd">DROP</span> <span class="kwrd">TABLE</span> <span class="kwrd">IF</span> <span class="kwrd">EXISTS</span> RecommendationsStaged;
<span class="kwrd">CREATE</span> <span class="kwrd">EXTERNAL</span> <span class="kwrd">TABLE</span> RecommendationsStaged (
    USERID <span class="kwrd">INT</span>,
    RECOMMENDATIONS STRING
)
<span class="kwrd">ROW</span> FORMAT DELIMITED FIELDS TERMINATED <span class="kwrd">BY</span> <span class="str">'\t'</span>
LINES TERMINATED <span class="kwrd">BY</span> <span class="str">'\n'</span>
LOCATION <span class="str">'${hiveconf:MahoutStaging}'</span>;

INSERT OVERWRITE <span class="kwrd">TABLE</span> RecommendationsStaged
<span class="kwrd">SELECT</span>
    USERID,
    REGEXP_REPLACE(
        REGEXP_REPLACE(RECOMMENDATIONS, 
                "\\[", ""), 
            "\\]", "") <span class="kwrd">AS</span> RECOMMENDATIONS
<span class="kwrd">FROM</span> RecommendationsRaw;</pre>
<h5>Step 3 &ndash; Create a new Hive table over leverage Hive&rsquo;s support for complex types (arrays and stucts)</h5>
<pre class="csharpcode"><span class="kwrd">DROP</span> <span class="kwrd">TABLE</span> <span class="kwrd">IF</span> <span class="kwrd">EXISTS</span> MahoutRecommendations;
<span class="kwrd">CREATE</span> <span class="kwrd">EXTERNAL</span> <span class="kwrd">TABLE</span> MahoutRecommendations (
    USERID <span class="kwrd">INT</span>,
    RECOMMENDATIONS <span class="kwrd">ARRAY</span>&lt;STRUCT&lt;BEERID:STRING,RATING:STRING&gt;&gt;
)
<span class="kwrd">ROW</span> FORMAT DELIMITED 
FIELDS TERMINATED <span class="kwrd">BY</span> <span class="str">'\t'</span>
COLLECTION ITEMS TERMINATED <span class="kwrd">BY</span> <span class="str">','</span>
<span class="kwrd">MAP</span> KEYS TERMINATED <span class="kwrd">BY</span> <span class="str">':'</span>
LINES TERMINATED <span class="kwrd">BY</span> <span class="str">'\n'</span>
LOCATION <span class="str">'${hiveconf:MahoutStaging}'</span>;</pre>
<h5>Step 4 &ndash; Unpivot the data and write to a CSV formatted file</h5>
<pre class="csharpcode"><span class="kwrd">DROP</span> <span class="kwrd">TABLE</span> <span class="kwrd">IF</span> <span class="kwrd">EXISTS</span> Recommendations;
<span class="kwrd">CREATE</span> <span class="kwrd">EXTERNAL</span> <span class="kwrd">TABLE</span> Recommendations (
    USERID <span class="kwrd">INT</span>,
    BEERID <span class="kwrd">INT</span>,
    RATING STRING
)
<span class="kwrd">ROW</span> FORMAT DELIMITED FIELDS TERMINATED <span class="kwrd">BY</span> <span class="str">','</span>
LINES TERMINATED <span class="kwrd">BY</span> <span class="str">'\n'</span>
LOCATION <span class="str">'${hiveconf:RecommendationsOutput}'</span>;

INSERT OVERWRITE <span class="kwrd">TABLE</span> Recommendations
<span class="kwrd">SELECT</span>
   USERID,
   r.BEERID,
   r.RATING
<span class="kwrd">FROM</span> MahoutRecommendations
<span class="kwrd">LATERAL</span> <span class="kwrd">VIEW</span> explode(RECOMMENDATIONS) RECOMMENDATION_TABLE <span class="kwrd">AS</span> r;</pre>
<p>Taking all four pieces of the script, we assemble them into a single file with an *.hql extension. The file should then be uploaded your blob storage account. The Azure Data Factory pipeline will reference this script based on the configuration described in my previous blog post.</p>
<h3>Creating the SQL Server Table Type &amp; Procedures</h3>
<p>To efficiently load data back into our Azure SQL Database we use the definition of a custom table type and a stored procedure. Our recommendation data is then passed as a table variable to the stored procedure which is ultimately responsible for handling the heavy lifting and performing any last transformations required to load the data into the database table structures. The table-type and stored procedure DDL are listed below and will be reference later when we specify our Azure Data factory pipeline.</p>
<pre class="csharpcode"><span class="kwrd">CREATE</span> TYPE [dbo].[RecommendationType] <span class="kwrd">AS</span> <span class="kwrd">TABLE</span>(
    [UserID] [<span class="kwrd">int</span>] <span class="kwrd">NULL</span>,
    [BeerID] [<span class="kwrd">int</span>] <span class="kwrd">NULL</span>,
    [EstimatedScore] [<span class="kwrd">decimal</span>](18, 2) <span class="kwrd">NULL</span>
)</pre>
<pre class="csharpcode"><span class="kwrd">CREATE</span> <span class="kwrd">PROCEDURE</span> [dbo].[IngressUserRecommendations]
    @Recommendations dbo.RecommendationType READONLY
<span class="kwrd">AS</span>
    <span class="kwrd">BEGIN</span> TRY
        <span class="kwrd">BEGIN</span> <span class="kwrd">TRAN</span>
            <span class="kwrd">DELETE</span> <span class="kwrd">FROM</span> Recommendation

            INSERT Recommendation (UserID, BeerID, EstimatedScore)
            <span class="kwrd">SELECT</span>
                UserID, BeerID, EstimatedScore
            <span class="kwrd">FROM</span> @Recommendations
        <span class="kwrd">COMMIT</span> <span class="kwrd">TRAN</span>
    <span class="kwrd">END</span> TRY
    <span class="kwrd">BEGIN</span> CATCH
        <span class="kwrd">IF</span> <span class="preproc">@@TRANCOUNT</span> &gt; 0
        <span class="kwrd">BEGIN</span>
            <span class="kwrd">ROLLBACK</span> <span class="kwrd">TRAN</span>
        <span class="kwrd">END</span>
    <span class="kwrd">END</span> CATCH
GO</pre>
<h3>Wiring in the Azure Data Factory Pipeline</h3>
<p>Recall from my prior post that we defined a MahoutRecommendations dataset that acts as the input into this new pipeline. Before we create the pipeline however, we need to define two new datasets. The first dataset represents the output generated by the fourth step of the Hive job in out Azure Blob Storage account. For this dataset, we need to define a schema structure since it will be used to map columns and load the data back into our Azure SQL database. The JSON configuration is provided below.</p>
<pre class="csharpcode">{
    "name": "Recommendations",
    "properties":
    {
        "structure":  
        [ 
            { "name": "UserID", "type": "INT"},
            { "name": "BeerID", "type": "INT"},
            { "name": "EstimatedScore", "type": "STRING"}
        ],
        "location": 
        {
            "type": "AzureBlobLocation",
            "folderPath": "dfdemo/recommendations/{Year}_{Month}_{Day}/",
            "format":
            {
                "type": "TextFormat",
                "columnDelimiter": ","
            },
            "linkedServiceName": "StorageLinkedService",
            "partitionedBy":
            [
                { name: "Year", value: { type: "DateTime", date: "SliceStart", format: "yyyy" } },
                { name: "Month", value: { type: "DateTime", date: "SliceStart", format: "%M" } },
                { name: "Day", value: { type: "DateTime", date: "SliceStart", format: "%d" } }
            ]
        },
        "availability": 
        {
            "frequency": "Day",
            "interval": 1            
        }
    }
}</pre>
<p>The second dataset acts as our connection back to the Azure SQL Database. Note in the JSON below, I went ahead and specified the Recommendations table in the dataset, but that will not be used by our pipeline.</p>
<pre class="csharpcode">{
    "name": "RecommendationsSQL",
    "properties":
    {
        "location":
        {
            "type": "AzureSqlTableLocation",
            "tableName": "Recommendations",
            "linkedServiceName": "AzureSqlLinkedService"
        },
        "availability": 
        {
            "frequency": "Day",
            "interval": 1            
        }
    }
}</pre>
<p>Finally, we define the pipeline. This pipeline use the MahoutRecommendations dataset as a input and consists of two activities: a HDInsight Activity and a Copy Activity. The HDInsight Activity references the HDInsight Linked Service defined in the previous blog entry and uses the Hive transformation to execute the *.hql script we defined above. The extended properties node is used to pass the various Hive configuration properties required by the script. The Copy Activity handles the egress of data from the Hive transformation back to the Azure SQL database. In this configuration we reference our two new datasets and configure the source and sinks for the movement. In the sink definition we reference the new SQL Table Type and Stored Procedure created above. The entire JSON configuration winds up looking as follows:</p>
<pre class="csharpcode">{
    "name": "EgressPipeline",
    "properties":
    {
        "description" : "Unpivot the Mahout Recommendation output and load to Azure SQL Database",
        "activities":
        [
            {
                "name": "Unpivot",
                "description": "Unpivot Mahout Recommendation output",
                "type": "HDInsightActivity",
                "inputs": [ {"name": "MahoutRecommendations"}],
                "outputs": [ {"name": "Recommendations"} ],
                "linkedServiceName": "HDILinkedService",
                "transformation":
                {
                    "type": "Hive",
                    "extendedProperties":
                    {
                        "MahoutInput": "$$Text.Format(
                            'wasb://<span class="kwrd">&lt;</span><span class="html">CONTAINER</span><span class="kwrd">&gt;</span>@<span class="kwrd">&lt;</span><span class="html">ACCOUNT</span><span class="kwrd">&gt;</span>.blob.core.windows.net/mahout/recommendations/{0:yyyy_MM_dd}/', 
                                Time.AddHours(SliceStart, 0))",
                        "MahoutStaging": "$$Text.Format(
                            'wasb://<span class="kwrd">&lt;</span><span class="html">CONTAINER</span><span class="kwrd">&gt;</span>@<span class="kwrd">&lt;</span><span class="html">ACCOUNT</span><span class="kwrd">&gt;</span>.blob.core.windows.net/mahout/stage/{0:yyyy_MM_dd}/', 
                                Time.AddHours(SliceStart, 0))",
                        "RecommendationsOutput": "$$Text.Format(
                            'wasb://<span class="kwrd">&lt;</span><span class="html">CONTAINER</span><span class="kwrd">&gt;</span>@<span class="kwrd">&lt;</span><span class="html">ACCOUNT</span><span class="kwrd">&gt;</span>.blob.core.windows.net/recommendations/{0:yyyy_MM_dd}/', 
                                Time.AddHours(SliceStart, 0))"
                    },        
                    "scriptpath": "dfdemo\\scripts\\unpivotrecommendations.hql",                
                    "scriptLinkedService": "StorageLinkedService"
                },
                "policy":
                {
                    "concurrency": 1,
                    "executionPriorityOrder": "OldestFirst",
                    "retry": 1,
                    "timeout": "01:00:00"
                }
            },
            {
                "name": "EgressData",
                "description": "Egress recommendations to Azure SQL DB",        
                "type": "CopyActivity",
                "inputs": [ {"name": "Recommendations"} ],
                "outputs": [ {"name": "RecommendationsSQL"} ],    
                "transformation":
                {
                    "source":
                    {                               
                        "type": "BlobSource"
                    },
                    "sink":
                    {
                        "type": "SqlSink",
                        "SqlWriterTableType": "RecommendationType",
                        "SqlWriterStoredProcedureName": "IngressUserRecommendations"
                    }            
                },
                "Policy":
                {
                    "concurrency": 1,
                    "executionPriorityOrder": "OldestFirst",
                    "style": "StartOfInterval",
                    "retry": 0,
                    "timeout": "01:00:00"
                }
            }
        ]
      }
}
</pre>
<p>As in the previous post, to update the data factory with all the new pieces we use PowerShell.</p>
<h3>Wrap-Up</h3>
<p>Using the <a href="https://portal.azure.com/" target="_blank">Azure Portal</a>, you can browse the completed Data Factory using the diagram view (see below) to see the final result. When the pipeline runs it will create a HDInsight Cluster on-demand (if one does not exist from a prior step), execute the Hive script transformation and then load the data to the Azure SQL Database.</p>
<p><a href="https://bluewatersql.files.wordpress.com/2015/02/image5.png"><img style="display: inline; border-width: 0;" title="image" src="https://bluewatersql.files.wordpress.com/2015/02/image_thumb5.png" alt="image" width="710" height="326" border="0" /></a></p>
<p>&nbsp;</p>
<p>This example used multiple pieces of the new Azure Data Factory service but has only scratched the surface of its overall capabilities. Keep in mind that this service is still in Preview and will evolve. This evolution may change some of the current capabilities discussed and will certainly introduce new capabilities. I hope these posts sparks your interest in this new technology and moves you to give it a shot in your own use case. As always feel free to let me know if you have any questions or suggestions. Till next time!</p>
<h1>Chris</h1>]]></content:encoded>
    </item>
    <item>
      <title>Something's Brewing with Azure Data Factory Part 2</title>
      <link>https://docs.microsoft.com/archive/blogs/bluewatersql/somethings-brewing-with-azure-data-factory-part-2</link>
      <pubDate>Mon, 02 Feb 2015 05:10:04 GMT</pubDate>
      <dc:creator><![CDATA[Bluewater SQL]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/bluewatersql/2015/02/02/somethings-brewing-with-azure-data-factory-part-2/</guid>
      <description><![CDATA[In my last post (HERE), I started hacking my way through the new Azure Data Factory service to...]]></description>
      <content:encoded><![CDATA[<p>In my last post (<a title="Something&rsquo;s Brewing with Azure Data Factory" href="https://bluewatersql.wordpress.com/2015/01/27/somethings-brewing-with-azure-data-factory/">HERE</a>), I started hacking my way through the new Azure Data Factory service to automate my beer recommendation demo. The first post was all about setting up the necessary scaffolding and then building that first pipeline to move data from the Azure SQL Database into Azure Blob Storage. In this post, we will do something interesting with that data, by using the Mahout library to apply collaborative filtering to generate user-based recommendations. Without further delay, lets get started.</p>
<h3>Getting Ready to Ride</h3>
<p><a href="https://mahout.apache.org/" target="_blank">Mahout</a>is a scalable machine learning library that runs as MapReduce job within an HDInsight cluster. While a discussion of Mahout particulars is outside the scope of this blog, in order to leverage this library we simply need to execute a MapReduce job with the correct configuration. Recalling from the prior post, we defined linked services which allowed for access to Azure SQL and Blob data source, then datasets which act as both inputs and outputs for pipelines which are responsible for the heavy lifting. Before worrying about the running any Mahout job we first need to define a linked service for a HDInsight cluster Two options exists for creating a HDInsight cluster. You can either bring your own HDInsight cluster or have one created on-demand by Azure Data Factory. For this demo, we will use the on-demand variety. To create an on-demand cluster, we first must create and configure a LinkedService which access to the Azure Blob Storage account that will serve as a container for HDInsight as seen in the JSON below.</p>
<pre class="csharpcode">{
    <span class="str">"name"</span>: <span class="str">"HDIStorageLinkedService"</span>,
    <span class="str">"properties"</span>:
    {
        <span class="str">"type"</span>: <span class="str">"AzureStorageLinkedService"</span>,
        <span class="str">"connectionString"</span>: <span class="str">"DefaultEndpointsProtocol=https;AccountName=&lt;ACCOUNT /&gt;;AccountKey=&lt;ACCOUNT_KEY /&gt;"</span>
    }
}</pre>
<p>Next, we use JSON to configure the actual on-demand HDInsight service.</p>
<pre class="csharpcode">{
    <span class="str">"name"</span>: <span class="str">"HDILinkedService"</span>,
    <span class="str">"properties"</span>: 
    {
    <span class="str">"type"</span>: <span class="str">"HDInsightOnDemandLinkedService"</span>,
    <span class="str">"clusterSize"</span>: <span class="str">"4"</span>,
    <span class="str">"jobsContainer"</span>: <span class="str">"DataFactoryJobs"</span>,
    <span class="str">"timeToLive"</span>: <span class="str">"00:05:00"</span>,
    <span class="str">"linkedServiceName"</span>: <span class="str">"HDIStorageLinkedService"</span>
    }
}</pre>
<p>The final step is to create both linked services using the following PowerShell command.</p>
<pre class="csharpcode">New-AzureDataFactoryLinkedService -ResourceGroupName $ns -DataFactoryName $df -File .\HDIStorageLinkedService.json
New-AzureDataFactoryLinkedService -ResourceGroupName $ns -DataFactoryName $df -File .\HDILinkedService.json</pre>
<p>With the required Linked Services in place, we can turn our attention to inputs and outputs. The input we will use for our new Pipeline is the output from the Ingress step (the UserRatingsBlob dataset) we defined in the prior post. That means that it is only necessary to define one new dataset. In this step our output dataset is only used as scaffolding to wire our pipelines together. This makes it unnecessary to define a structure or schema. To define the new Mahout output data set we can use the following JSON:</p>
<pre class="csharpcode">{
    <span class="str">"name"</span>: <span class="str">"MahoutRecommendations"</span>,
    <span class="str">"properties"</span>:
    {
        <span class="str">"location"</span>: 
        {
            <span class="str">"type"</span>: <span class="str">"AzureBlobLocation"</span>,
            <span class="str">"folderPath"</span>: <span class="str">"&lt;CONTAINER /&gt;/mahout/recommendations/{Year}_{Month}_{Day}/"</span>,
            <span class="str">"linkedServiceName"</span>: <span class="str">"StorageLinkedService"</span>,
            <span class="str">"partitionedBy"</span>:
            [
                { name: <span class="str">"Year"</span>, <span class="kwrd">value</span>: { type: <span class="str">"DateTime"</span>, date: <span class="str">"SliceStart"</span>, format: <span class="str">"yyyy"</span> } },
                { name: <span class="str">"Month"</span>, <span class="kwrd">value</span>: { type: <span class="str">"DateTime"</span>, date: <span class="str">"SliceStart"</span>, format: <span class="str">"%M"</span> } },
                { name: <span class="str">"Day"</span>, <span class="kwrd">value</span>: { type: <span class="str">"DateTime"</span>, date: <span class="str">"SliceStart"</span>, format: <span class="str">"%d"</span> } }
            ]
        },
        <span class="str">"availability"</span>: 
        {
            <span class="str">"frequency"</span>: <span class="str">"day"</span>,
            <span class="str">"interval"</span>: 1
        }
    }
}</pre>
<p>After the JSON file has been created on your local file system, the PowerShell command below will create the new dataset.</p>
<pre class="csharpcode">New-AzureDataFactoryTable -ResourceGroupName $ns -DataFactoryName $df &ndash;File .\MahoutRecommendations.json</pre>
<p>After all the required Linked Services and datasets are created, we can turn our attention to the Pipeline that will ultimately generate the recommendations.</p>
<h3>Ride the Elephant</h3>
<p>The Azure Data Factory contains a number of built in transformation types that allow you to manipulate data using Hive, Pig, MapReduce or even a bit of custom C# code. Since Mahout runs as a MapReduce job, we will leverage the MapReduce type using the JSON below.</p>
<pre class="csharpcode">{  
       <span class="str">"name"</span>: <span class="str">"MahoutPipeline"</span>,       
       <span class="str">"properties"</span>:{  
          <span class="str">"description"</span>:<span class="str">"Pipeline uses collaborative filtering to generate recommendations"</span>,
          <span class="str">"activities"</span>:[  
             {  
                <span class="str">"name"</span>:<span class="str">"MahoutActivity"</span>,
                <span class="str">"description"</span>:<span class="str">"Map Reduce job to generate Mahout recommendations"</span>,
                <span class="str">"type"</span>:<span class="str">"HDInsightActivity"</span>,
                <span class="str">"inputs"</span>:[  
                   {  
                      <span class="str">"Name"</span>:<span class="str">"UserRatingsBlob"</span>
                   }
                ],
                <span class="str">"outputs"</span>:[  
                   {  
                      <span class="str">"Name"</span>:<span class="str">"MahoutRecommendations"</span>
                   }
                ],
                <span class="str">"linkedServiceName"</span>:<span class="str">"HDILinkedService"</span>,
                <span class="str">"transformation"</span>:{  
                   <span class="str">"type"</span>:<span class="str">"MapReduce"</span>,
                   <span class="str">"className"</span>:<span class="str">"org.apache.mahout.cf.taste.hadoop.item.RecommenderJob"</span>,
                   <span class="str">"jarFilePath"</span>:<span class="str">"dfdemo/mahout/jars/mahout-examples-0.9.0.2.1.9.0-2196-job.jar"</span>,
                   <span class="str">"jarLinkedService"</span>:<span class="str">"StorageLinkedService"</span>,
                   <span class="str">"arguments"</span>:[  
                      <span class="str">"-s"</span>,
                      <span class="str">"SIMILARITY_PEARSON_CORRELATION"</span>,
                      <span class="str">"--input"</span>,
                      <span class="str">"wasb://@.blob.core.windows.net/reviews/"</span>,
                      <span class="str">"--output"</span>,
                      <span class="str">"$$Text.Format('wasb://@.blob.core.windows.net/mahout/recommendations/{0:yyyy_MM_dd}/', Time.AddHours(SliceStart, 0))"</span>,    
                      <span class="str">"--maxSimilaritiesPerItem"</span>,
                      <span class="str">"10"</span>,
                      <span class="str">"--tempDir"</span>,
                      <span class="str">"$$Text.Format('wasb://@.blob.core.windows.net/mahout/temp/{0:yyyy_MM_dd}/', Time.AddHours(SliceStart, 0))"</span>                        
                   ]
                },
                <span class="str">"policy"</span>:{  
                   <span class="str">"concurrency"</span>:1,
                   <span class="str">"executionPriorityOrder"</span>:<span class="str">"OldestFirst"</span>,
                   <span class="str">"retry"</span>:1,
                   <span class="str">"timeout"</span>:<span class="str">"01:00:00"</span>
                }
             }
          ]
       }
    }</pre>
<p>A couple of things to point out in the configuration. Beyond the the input, outputs and linked services I want to call your attention to the MapReduce specific items. Note that the Mahout jar is stored in a blob storage container (dfdemo/mahout/jars) and a linked service is provided to allow for access to the library. Next, note that all the command-line or runtime arguments required by the Mahout RecommenderJob class are define in the arguments configuration section. These include the similarity calculation method, the maximum number of recommendations to generate for each user, the input, output and temp directories that will be used when the job runs. Finally, Mahout presents an interesting challenge since it neither cleans-up after itself nor allows for overwriting of files. This means that both the Temp and less-so the Output directory pose a potential issue in a system where Mahout will be run daily or on whatever cyclical schedule you define. To avoid errors, it is necessary to use the slice to make these folders unique on each run.</p>
<pre class="csharpcode">New-AzureDataFactoryPipeline -ResourceGroupName $ns -DataFactoryName $df &ndash;File .\PipeLines\MahoutPipeline.json
Set-AzureDataFactoryPipelineActivePeriod -ResourceGroupName $ns -DataFactoryName $df &ndash;Name MahoutPipeline -StartDateTime 2015-01-24Z -EndDateTime 2015-01-24Z -Force</pre>
<p>Lastly, after the JSON config file is in place, create the pipeline and set the activity period to create the slices and run the pipeline as seen in the preceding code snippet.</p>
<h3>Wrap-Up</h3>
<p>Using the <a href="https://portal.azure.com/" target="_blank">Azure Portal</a> UI, verify the Data Factory is in order and that the diagram for the workflow looks similar to the screenshot below.</p>
<p><a href="https://bluewatersql.files.wordpress.com/2015/02/image.png"><img style="display: inline; border: 0;" title="image" src="https://bluewatersql.files.wordpress.com/2015/02/image_thumb.png" alt="image" width="215" height="244" border="0" /></a></p>
<p><a href="https://bluewatersql.files.wordpress.com/2015/02/image1.png"><img style="display: inline; border: 0;" title="image" src="https://bluewatersql.files.wordpress.com/2015/02/image_thumb1.png" alt="image" width="572" height="272" border="0" /></a></p>
<p>When the job runs, the Data Factory will spin up a HDInsight cluster on-demand using the configuration you specified. This step will take longer than anything else in the workflow. You can monitor the workflow by observing the event log or by verifying that that the slice is running as expected by drilling into the MahoutRecommendations dataset.</p>
<p><a href="https://bluewatersql.files.wordpress.com/2015/02/image2.png"><img style="display: inline; border: 0;" title="image" src="https://bluewatersql.files.wordpress.com/2015/02/image_thumb2.png" alt="image" width="343" height="393" border="0" /></a></p>
<p><a href="https://bluewatersql.files.wordpress.com/2015/02/image3.png"><img style="display: inline; border: 0;" title="image" src="https://bluewatersql.files.wordpress.com/2015/02/image_thumb3.png" alt="image" width="561" height="338" border="0" /></a></p>
<p>After the job completes, you can browse the recommendation results from blob storage.</p>
<p><a href="https://bluewatersql.files.wordpress.com/2015/02/image4.png"><img style="display: inline; border: 0;" title="image" src="https://bluewatersql.files.wordpress.com/2015/02/image_thumb4.png" alt="image" width="560" height="273" border="0" /></a></p>
<p>In the next post, we will wrap-up this demo as we use the Hive transformation to un-pivot the Mahout recommendation results and then the CopyActivity to load or egress the data back to our Azure SQL Database.</p>
<p>Till next time!</p>
<h1>Chris</h1>]]></content:encoded>
    </item>
    <item>
      <title>Something's Brewing with Azure Data Factory</title>
      <link>https://docs.microsoft.com/archive/blogs/bluewatersql/somethings-brewing-with-azure-data-factory</link>
      <pubDate>Tue, 27 Jan 2015 12:24:00 GMT</pubDate>
      <dc:creator><![CDATA[Bluewater SQL]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/bluewatersql/2015/01/27/somethings-brewing-with-azure-data-factory/</guid>
      <description><![CDATA[Awhile back I put together a presentation to show off HDInsight using Mahout and most...]]></description>
      <content:encoded><![CDATA[<p>Awhile back I put together a presentation to show off HDInsight using Mahout and most everyone&rsquo;s favorite Beer. The concept was simple. A spartan website allowed users to create a website and rate beers. The ratings were then fed into Mahout to generate recommendations using Collaborative filtering. Looking back, the process I used was good enough for demos but was pretty rough. Oozie was fully supported so I rolled my own solution. I used Sqoop to move data from an Azure SQL database to Azure Blob Storage, ran one Mahout job (MapReduce) to generate recommendations, another MapReduce job to unpivot the results before loading the results back to the Azure SQL database again using Sqoop. Your head is probably spinning after reading that and while it was messy, it worked and at the time it was what we had to work with. With Azure Data Factory there is a better and more efficient way. The next couple of posts will walk-through rebuilding that demo using a Data Factory to orchestrate both data movement and job execution.</p>
<h3>The Set-Up</h3>
<p>Before diving in, lets set the stage with a little background. The base of this demo is a website in which users can browse and rate beers and subsequently receive intelligent recommendations. Beers are rated on a scale from 1 to 5. Users and their ratings data is stored in a Azure SQL database called Beer. The review data is run through Mahout using collaborative filtering.</p>
<table style="width: 800px;" border="0" cellspacing="0" cellpadding="2">
<tbody>
<tr>
<td valign="top" width="400"><img style="display: inline; border-width: 0;" title="image" src="https://bluewatersql.files.wordpress.com/2015/01/image_thumb.png" alt="image" width="402" height="209" border="0" /></td>
<td valign="top" width="400"><a href="https://bluewatersql.files.wordpress.com/2015/01/image.png"><img style="display: inline; border-width: 0;" title="image" src="https://bluewatersql.files.wordpress.com/2015/01/image_thumb1.png" alt="image" width="397" height="196" border="0" /></a></td>
</tr>
</tbody>
</table>
<p>Before you get started you want to make sure you have a couple of things. You will need an Azure account, access to the new <a href="https://portal.azure.com/" target="_blank">Azure Portal</a> and <a href="https://azure.microsoft.com/en-us/documentation/articles/install-configure-powershell/" target="_blank">Azure PowerShell</a>installed and configured on your machine. The example I will present uses an Azure SQL database, Azure Blob storage and of course Azure Data Factory. For brevity, I will not discuss setting up Azure resources outside of the Data Factory.</p>
<h3>Step 1: Creating the Data Factory</h3>
<p>The Data Factory is the container for all subsequent activities we will discuss. There are currently two ways to create the Data Factory: the Azure Portal UI and PowerShell. Using the Azure Portal to create the Data Factory is a trivial task. Click on the &lsquo;+ New&rsquo; button and select Azure Data Factory. Within the dialog you will need to specify a globally unique name, a resource group, the subscription (if you have multiple) and the geographical region.</p>
<table style="width: 800px;" border="0" cellspacing="0" cellpadding="2">
<tbody>
<tr>
<td valign="top" width="400"><a href="https://bluewatersql.files.wordpress.com/2015/01/image1.png"><img style="display: inline; border-width: 0;" title="image" src="https://bluewatersql.files.wordpress.com/2015/01/image_thumb2.png" alt="image" width="397" height="196" border="0" /></a></td>
<td valign="top" width="400"><a href="https://bluewatersql.files.wordpress.com/2015/01/image2.png"><img style="display: inline; border-width: 0;" title="image" src="https://bluewatersql.files.wordpress.com/2015/01/image_thumb3.png" alt="image" width="124" height="244" border="0" /></a></td>
</tr>
</tbody>
</table>
<p>You can likewise perform the same operation using Azure PowerShell. Before you begin executing commands, you&rsquo;ve switched to AzureResourceManager mode and also that you are authenticated and your subscription is selected.</p>
<pre class="csharpcode">Switch-AzureMode AzureResourceManager

Add-AzureAccount 

Select-AzureSubscription -SubscriptionName <span class="str">"Visual Studio Ultimate with MSDN"</span></pre>
<p>To create the Data Factory through PowerShell the following command is used. Please note that I am using PowerShell variables to simplify my script and will not repeat the declarations subsequently.</p>
<pre class="csharpcode">$df = <span class="str">"Brewhaus"</span>
$ns = <span class="str">"BluewaterDataFactory"</span>
$loc = <span class="str">"West US"</span>

<span class="rem">#Create the Data Factory</span>
New-AzureDataFactory -ResourceGroupName $ns -Name $df -Location $loc -Force -ErrorAction Stop</pre>
<p>After PowerShell has reported that the Data Factory was created successful, you can browse the Data Factory dashboard in the Azure Portal. Tip: To simplify working with this dashboard is to pin it to your Startboard to avoid having to constantly browse for it. <a href="https://bluewatersql.files.wordpress.com/2015/01/image3.png"><img style="display: inline; border-width: 0;" title="image" src="https://bluewatersql.files.wordpress.com/2015/01/image_thumb4.png" alt="image" width="373" height="501" border="0" /></a></p>
<h3>Step 2: Defining Linked Services</h3>
<p>With the Data Factory in place, the next step is to define the Linked Services required for our workflow. Linked Services can be define as one of five types: AzureStorageLinkedService, AzureSqlLinkedService, OnPremiseSqlLinkedService, HDInsightOnDemandLinkedService and HDInsightBYOCLinkedService. For our purposes we are only concerns with connecting two an Azure SQL database and Azure Blob Storage. This requires two Linked Services one for each. While Linked Services can be defined through the portal, I will define these using a JSON definition and PowerShell. To define the Linked Service for an Azure SQL database, we construct the required JSON containing a connection string to the appropriate database as seen below.</p>
<pre class="csharpcode">{
    <span class="str">"name"</span>: <span class="str">"AzureSqlLinkedService"</span>,
    <span class="str">"properties"</span>:
    {
        <span class="str">"type"</span>: <span class="str">"AzureSqlLinkedService"</span>,
        <span class="str">"connectionString"</span>: <span class="str">" Server=tcp:&lt;SERVER&gt;.database.windows.net,1433; Database=Beer; User ID=&lt;USER_ID&gt;; Password=&lt;PASSWORD&gt;; Trusted_Connection=False; Encrypt=True; Connection Timeout=30"</span>
    }
}</pre>
<p>For a storage account Linked Service, the JSON contains the blob storage account name and key.</p>
<pre class="csharpcode">{
    <span class="str">"name"</span>: <span class="str">"StorageLinkedService"</span>,
    <span class="str">"properties"</span>:
    {
        <span class="str">"type"</span>: <span class="str">"AzureStorageLinkedService"</span>,
        <span class="str">"connectionString"</span>: <span class="str">" DefaultEndpointsProtocol=https; AccountName=&lt;ACCOUNT_NAME&gt;; AccountKey=&lt;ACCOUNT_KEY&gt;"</span>
    }
}</pre>
<p>To create the Linked Services the following PowerShell commands are used taking care to use the correct path to the JSON configuration files on your machine.</p>
<pre class="csharpcode"><span class="rem">#Create Linked Services</span>
New-AzureDataFactoryLinkedService -ResourceGroupName $ns -DataFactoryName $df -File .\AzureSqlLinkedService.json
New-AzureDataFactoryLinkedService -ResourceGroupName $ns -DataFactoryName $df -File .\StorageLinkedService.json</pre>
<p>These Linked Services function as connection managers for your Data Factory. In the subsequent steps, we will define datasets and pipelines which reference these connections for the purpose of either accessing or processing data.</p>
<h3>Step 3: Defining Datasets</h3>
<p>The datasets or more accurately tables that we define provide the input and output schemas needed for this workflow. These schemas are where our we define the column (name and data type) structure, the location as well as the availability of the data. Like Linked Services, we must define two Tables one for each using JSON. Please note that as of the writing of the post creating datasets through the portal UI is not supported. Starting with source data located in the Azure SQL database, it is necessary to pull only three columns of data (UserID, BeerID and OverallRating) for this exercise. Since the data is coming from an Azure SQL database it is not necessary to specify a structure as it will be inferred from the database schema. This table points to our Azure SQL Linked Service and references the BeerReview table which contains the needed data. This demo will use a daily pull and does not have any external dependencies as is reflected in the availability element below.</p>
<pre class="csharpcode">{
    <span class="str">"name"</span>: <span class="str">"UserRatings"</span>,
    <span class="str">"properties"</span>:
    {
        <span class="str">"location"</span>:
        {
            <span class="str">"type"</span>: <span class="str">"AzureSqlTableLocation"</span>,
            <span class="str">"tableName"</span>: <span class="str">"BeerReview"</span>,
            <span class="str">"linkedServiceName"</span>: <span class="str">"AzureSqlLinkedService"</span>
        },
        <span class="str">"availability"</span>: 
        {
            <span class="str">"frequency"</span>: <span class="str">"Day"</span>,
            <span class="str">"interval"</span>: 1,
            "waitonexternal": {}           
        }
    }
}</pre>
<p>The blob data is an exact mirror of our source data. The big difference in each definition is how the location is specified. With blob storage we are not only writing data files to the configured account but we are partitioning the data into monthly folders. This is also where we could define any formatting options such as column and row delimiters or even the serializer used (current Text or Avro). For our demo, we will accept the defaults.</p>
<pre class="csharpcode">{
    <span class="str">"name"</span>: <span class="str">"UserRatingsBlob"</span>,
    <span class="str">"properties"</span>:
    {
        <span class="str">"location"</span>: 
        {
            <span class="str">"type"</span>: <span class="str">"AzureBlobLocation"</span>,
            <span class="str">"folderPath"</span>: <span class="str">"dfdemo/userratings/year={Year}/month={Month}/"</span>,
            <span class="str">"fileName"</span>: <span class="str">"ratings{Year}{Month}{Day}"</span>,
            <span class="str">"partitionedBy"</span>:
            [
                { name: <span class="str">"Year"</span>, <span class="kwrd">value</span>: { type: <span class="str">"DateTime"</span>, date: <span class="str">"SliceStart"</span>, format: <span class="str">"yyyy"</span> } },
                { name: <span class="str">"Month"</span>, <span class="kwrd">value</span>: { type: <span class="str">"DateTime"</span>, date: <span class="str">"SliceStart"</span>, format: <span class="str">"%M"</span> } },
                { name: <span class="str">"Day"</span>, <span class="kwrd">value</span>: { type: <span class="str">"DateTime"</span>, date: <span class="str">"SliceStart"</span>, format: <span class="str">"%d"</span> } }
            ],
            <span class="str">"format"</span>:
            {
                <span class="str">"type"</span>: <span class="str">"TextFormat"</span>,
                <span class="str">"columnDelimiter"</span>: <span class="str">","</span>
            },
            <span class="str">"linkedServiceName"</span>: <span class="str">"StorageLinkedService"</span>
        },
        <span class="str">"availability"</span>: 
        {
            <span class="str">"frequency"</span>: <span class="str">"Day"</span>,
            <span class="str">"interval"</span>: 1            
        }
    }
}</pre>
<p>With the JSON in hand we can create both datasets using the following PowerShell snippet.</p>
<pre class="csharpcode">#Create Tables
New-AzureDataFactoryTable -ResourceGroupName $ns -DataFactoryName $df &ndash;File .\Tables\UserRatings.json
New-AzureDataFactoryTable -ResourceGroupName $ns -DataFactoryName $df &ndash;File .\Tables\UserRatingsBlob.json</pre>
<h3>Step 4: Creating a Pipeline</h3>
<p>The final piece in the little puzzle we have going is the pipeline. The data pipeline is where we tie together our input and output. Activities such as transforming or enriching the data are define in the pipeline as we will explore in the next post. For this post, we will define only a single activity, the built in CopyActivity. Like data sets previously there is currently no way to define pipeline in the Portal UI, so JSON and PowerShell will be our go-to solution. In the JSON, we reference the two datasets and define the transformation. The transformation uses a SQL Data Reader as the source and filters based on the slice date. Since both input and output schemas are identical it is not necessary to perform and mapping between the source and destination.</p>
<pre class="csharpcode">{
    <span class="str">"name"</span>: <span class="str">"CopyRatingsPipeline"</span>,
    <span class="str">"properties"</span>:
    {
        <span class="str">"description"</span> : <span class="str">"This pipelines moves User Ratings from an Azure SQL Database to Azure Blob Storage"</span>,
        <span class="str">"activities"</span>:
        [
            {
                <span class="str">"name"</span>: <span class="str">"CopyActivity"</span>,
                <span class="str">"description"</span>: <span class="str">"Data Mover"</span>, 
                <span class="str">"type"</span>: <span class="str">"CopyActivity"</span>,
                <span class="str">"inputs"</span>:  [ { <span class="str">"name"</span>: <span class="str">"UserRatings"</span>  } ],
                <span class="str">"outputs"</span>:  [ { <span class="str">"name"</span>: <span class="str">"UserRatingsBlob"</span> } ],
                <span class="str">"transformation"</span>:
                {
                    <span class="str">"source"</span>:
                    {
                        <span class="str">"type"</span>: <span class="str">"SqlSource"</span>,
                        <span class="str">"SqlReaderQuery"</span>: <span class="str">"$$Text.Format(' SELECT UserID, BeerID, Overall FROM dbo.BeerReview WHERE [ReviewDate] = \\'{0:MM/dd/yyyy}\\'', Time.AddHours(SliceStart, 0))"</span>
                    },
                    <span class="str">"sink"</span>:
                    {
                        <span class="str">"type"</span>: <span class="str">"BlobSink"</span>
                    }
                },
                <span class="str">"policy"</span>:
                {
                    <span class="str">"Concurrency"</span>: 1,
                    <span class="str">"ExecutionPriorityOrder"</span>: <span class="str">"OldestFirst"</span>,
                    <span class="str">"Retry"</span>: 1,
                    <span class="str">"Timeout"</span>: <span class="str">"01:00:00"</span>
                }
            }
        ]
    }
}</pre>
<p>With the JSON definition we can use PowerShell to create the pipeline as seen below.</p>
<pre class="csharpcode">#Create Pipelines
New-AzureDataFactoryPipeline -ResourceGroupName $ns -DataFactoryName $df &ndash;File .\PipeLines\CopyRatingsPipeline.json</pre>
<p>After the PowerShell command completes successfully, browse can browse your Data Factory in the Azure portal. You can see the Linked Services, Datasets and Pipeline that were all created in the preceding steps. From the summary or main dashboard, click on the &lsquo;Diagram&rsquo; button to browse a visual representation of the orchestration or workflow.</p>
<table style="width: 800px;" border="0" cellspacing="0" cellpadding="2">
<tbody>
<tr>
<td valign="top" width="400"><a href="https://bluewatersql.files.wordpress.com/2015/01/image4.png"><img style="display: inline; border: 0;" title="image" src="https://bluewatersql.files.wordpress.com/2015/01/image_thumb5.png" alt="image" width="377" height="495" border="0" /></a></td>
<td valign="top" width="400"><a href="https://bluewatersql.files.wordpress.com/2015/01/image5.png"><img style="display: inline; border: 0;" title="image" src="https://bluewatersql.files.wordpress.com/2015/01/image_thumb6.png" alt="image" width="402" height="204" border="0" /></a></td>
</tr>
</tbody>
</table>
<h3>Step 5: Setting the Pipeline Activity Period</h3>
<p>With all the pieces in place, it is only necessary to define a schedule for the pipeline. The PowerShell command takes the usual parameters as well as a start and optional end time. Set-AzureDataFactoryPipelineActivePeriod -ResourceGroupName $ns -DataFactoryName $df &ndash;Name CopyRatingsPipeline</p>
<blockquote>-StartDateTime 2015-01-24Z -EndDateTime 2015-02-02Z -Force</blockquote>
<p>After the activity period has been defined we can browse the slices and their processing status within the output data set. <a href="https://bluewatersql.files.wordpress.com/2015/01/image6.png"><img style="display: inline; border: 0;" title="image" src="https://bluewatersql.files.wordpress.com/2015/01/image_thumb7.png" alt="image" width="419" height="298" border="0" /></a></p>
<h3>Wrap-Up</h3>
<p>In this posts, we create a new Data Factory and then defined Linked Services which act as connection managers within the Data Flow. Next, we defined data sets that become the input and outputs for our pipeline. The pipeline is responsible for moving the data needed for recommendation generation from an Azure SQL database to the configured blob storage account. In the next post, we will expand the demo by creating an On-Demand cluster running the Mahout MapReduce job to generate beer recommendations. Till Next Time!</p>
<h1>Chris</h1>]]></content:encoded>
    </item>
    <item>
      <title>Hello…..Azure Data Factory!</title>
      <link>https://docs.microsoft.com/archive/blogs/bluewatersql/hello-azure-data-factory</link>
      <pubDate>Mon, 26 Jan 2015 07:12:00 GMT</pubDate>
      <dc:creator><![CDATA[Bluewater SQL]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/bluewatersql/2015/01/26/hello-azure-data-factory/</guid>
      <description><![CDATA[Overview
The boundaries between on-premise and cloud-born data continue to blur with more and more...]]></description>
      <content:encoded><![CDATA[<h3>Overview</h3>
<p>The boundaries between on-premise and cloud-born data continue to blur with more and more organization moving to hybrid data landscapes. The blurring of these lines introduces a number of complexities from data locality, to scale and even the diversity of the data which we must consume and processed. To meet these challenges head-on, Microsoft introduced a new managed cloud service known as Azure Data Factory (ADF).</p>
<h3>Four Pillars of Azure Data Factory</h3>
<p>So what is Azure Data Factory? That question is best answered by describing the four (current) pillars of ADF.</p>
<ol>
<li>Moving on-premise data to the cloud (and cloud data to on-premise)
<p>One of the primary use-cases of Azure Data Factory is as a pipeline to move or copy data across the on-premise/cloud boundary. Whether ingress or egress from the cloud, ADF is built to facilitate not only the orchestration of data movement but the transformations necessary to move your data to and from a variety of sources and destinations. The currently supported sources and destinations are: SQL Server (On-Premise), Azure Blobs, Azure Tables and Azure SQL databases. Please also note also that ADF can be used to move data from one cloud source to another.</p>
</li>
<li>Processing data at scale (HDInsight)
<p>While moving data from point A to point B is useful in a number of situations, often times it is necessary to transform and enrich your data along the way. Handling this processing can be non-trivial and when scale is an issue. The Azure Data Factory can handle processing data of any size by leveraging HDInsight. Using either a cluster of your own or one that Azure Data Factory creates on demand, you can process, transform and enrich your data using C#, Pig, Hive and even MapReduce.&nbsp;</p>
</li>
<li>Integrate and enrich disparate data
<p>The diversity of data and how you bring it all together presents interesting and unique challenges. How do you process that JSON data from your social media platform to enrich the more traditional and relational data from your on-premise CRM system? What about all that XML data provided by your partner or that old-school order management system? With Azure Data Factory, you can build both complex (and trivial)workflows, orchestrating the outputs from one pipeline into the inputs of another. For example, use one pipeline to shred that JSON data with a Pig Script, while another loads your transactional CRM data from an on-premise SQL Server into Azure blob storage. A third pipeline could then take both outputs, integrating them together using Hive or a Custom Activity written in C#.</p>
</li>
<li>Orchestrate &amp; Monitor data processing workflows
<p>If you done any amount of ETL work, you know first hand that its one thing to build a workflow and yet another to fully operationalize it. Too often in the ETL work things&nbsp; like logging and monitoring are after thoughts. Not with Azure Data Factory. Whether you use the Azure Dashboard Portal or PowerShell, you not only have robust access to the details of every process or workflow in your Data Factory but out of the box alerting in the event that something does go awry.</p>
</li>
</ol>
<h3>Wrap-Up</h3>
<p>So now that you have an idea of what the Azure Data Factory is, I suspect that some of you like me are itching to start using it. Over the next couple of posts, we will dig into the Data Factory, explore specific use cases and walk-through functional examples. If you would like to get a jump start, I&rsquo;d invite you to check out the documentation and examples over at: <a title="https://azure.microsoft.com/en-us/documentation/services/data-factory/" href="https://azure.microsoft.com/en-us/documentation/services/data-factory/">https://azure.microsoft.com/en-us/documentation/services/data-factory/</a>.</p>
<p>Lastly, keep in mind that Azure Data Factory is currently in preview. If you haven&rsquo;t previously worked with any of the Azure Services in Preview that basically means that it <span style="text-decoration: line-through;">can be</span> will be subject to changes with little to no notice as it evolves towards a more formal GA release.</p>
<h3>Till next time!</h3>
<h1>Chris</h1>]]></content:encoded>
    </item>
  </channel>
</rss>