尋覓Azure上的Athena和BigQuery (二):神奇的PolyBase

  在「數據湖」概念與理論逐漸深刻人心的今天,面向雲存儲的交互式查詢這個需求場景顯得愈發重要。這是由於原生的雲存儲(主要指S3這樣的對象存儲)既可以容納大容量的明細數據,又能在性能和成本間取得一個很好的平衡——若是它同時再支持複雜的即席分析查詢,那麼雲原生存儲就將成爲數據湖的最佳載體,對於實現數據分析人員的自由探索和應用系統的查詢集成都有着很是重要的意義。
  
  所以,在上一篇文章中,咱們圍繞着這個重要需求場景如何在Azure進行實現詳細地展開了咱們的探索。首先做爲參照,咱們在AWS環境中利用S3和Athena成功地對一個csv文件進行了SQL查詢。隨後,咱們主要使用Azure Data Lake Analytics (ADLA)配合Azure Data Lake Storage (ADLS)做存儲來實現了一樣的分析需求。值得注意的是,ADLA支持的查詢語言是U-SQL,一種混合了C#與SQL語法的獨特語言。
  
  然而,也如前文所提到,ADLA仍是存在一些固有侷限,也並未在Azure中國區上線。故而咱們有必要考慮和尋找Azure體系內的其餘選擇。今天的參賽選手,是源自SQL Server體系的PolyBase。
  
  初識PolyBase
  
  其實PolyBase這個稱謂最先出現於SQL Server 2012 Parallel Data Warehouse(PDW)中,該版本本質上是一個軟硬一體化的分佈式MPP數據庫。PolyBase組件賦予了在數據庫層面定義指向Hadoop/HDFS數據的外部表的能力,是幫助打通MPP數據庫與Hadoop大數據生態系統的重要橋樑。
  
  而PolyBase真正變得成熟而且廣爲人知,是自SQL Server 2016起,PolyBase技術正式地出如今了標準SQL Server中,畢竟PDW版本的受衆不夠普遍。此舉大大提高了SQL Server在大數據時代的綜合競爭力,使得微軟體系內的用戶經過T-SQL便可輕鬆地訪問和獲取Hadoop集羣中的數據。
  
  那麼,說了一大圈,源自SQL Server的PolyBase和Azure有什麼關係,和咱們今天的話題有什麼關係呢?這就得說到在微軟全面雲化的戰略之下,SQL Server其實也以多種不一樣形式遷移到了Azure雲端,造成了若干款不一樣的雲端數據服務產品(詳情參見筆者介紹SQL Server 2017的文章)。而PolyBase天然也一塊兒被帶到了雲端,並在支持訪問HDFS的基礎上還添加了訪問雲存儲的能力,這樣咱們就能夠經過PolyBase和你們熟悉的T-SQL語言來輕鬆實現面向雲存儲的交互式查詢了。
  
  (圖片來源:微軟PolyBase官方文檔)
  
  動手體驗
  
  讓咱們進入實踐環節。首先咱們須要尋找一個Azure上PolyBase技術的載體。SQL Server的Azure變體中有SQL Database、SQL Managed Instance、SQL Data Warehouse等相關產品,但支持經過PolyBase訪問雲存儲的目前僅有SQL Data Warehouse(下簡稱SQL DW)這一款。咱們就選擇它做爲查詢引擎。
  
  首先咱們準備一下實驗所需的數據,咱們一樣沿用上篇文章中的包含信用卡借貸數據的csv文件,把它放置到存儲帳戶的Blob中。咱們確認一下它的位置是在cloudpickersa這個存儲帳戶的sampledata容器中:
  
  接下來讓咱們請出今天的主角,建立一個SQL DW數據庫(本實驗使用美國西區資源,但相關服務均已在Azure中國上線),使用最新的Gen2版本:
  
  建立完成以後,就可使用你們所熟悉的SQL Server Management Studio(SSMS)進行鏈接了,除了個別圖標不一樣,其使用體驗與傳統SQL Server幾乎徹底一致。
  
  與Athena相似,PolyBase一樣是經過定義外部表的方式來對雲存儲中的數據和格式進行映射的。咱們來看一下具體的步驟。
  
  第一步,須要在剛纔新建的數據庫裏創建一個credential用以實現與指定存儲帳號訪問權限的對應:
  
  複製代碼
  
  CREATE MASTER KEY ENCRYPTION BY PASSWORD='MyPassw0rd';
  
  CREATE DATABASE SCOPED CREDENTIAL CloudpickerCredential
  
  WITH
  
  IDENTITY   = 'cloudpickersa'
  
  ,    SECRET     = 'j2PJqjIR1IfkDEESjWEIFzcgip...accesskeyismysupersecret...5VeqM2B+1bCWFosyvm4Kg=='
  
  using Microsoft.ML;
  
  聲明樣本數據文件和模型文件的文件路徑
  
  1
  
  2
  
  static readonly string _dataPath = Path.Combine(Environment.CurrentDirectory, "Data", "iris.data");
  
  static readonly string _modelPath = Path.Combine(Environment.CurrentDirectory, "Data", "IrisClusteringModel.zip");
  
  構造MLContext、IDataView,採用Trainer.KMeans進行模型訓練,造成模型文件:IrisClusteringModel.zip數據庫

  var mlContext = new MLContext(seed: 0);
  
  IDataView dataView = mlContext.Data.LoadFromTextFile<IrisData>(_dataPath, hasHeader: false, separatorChar: ',');
  
  string featuresColumnName = "Features";
  
  var pipeline = mlContext.Transforms
  
  .Concatenate(featuresColumnName, "SepalLength", "SepalWidth", "PetalLength", "PetalWidth")
  
  .Append(mlContext.Clustering.Trainers.KMeans(featuresColumnName, numberOfClusters: 3));
  
  var model = pipeline.Fit(dataView);
  
  using (var fileStream = new FileStream(_modelPath, FileMode.Create, FileAccess.Write, FileShare.Write))
  
  mlContext.Model.Save(model, dataView.Schema, fileStream);
  
  Console.WriteLine("完成模型訓練!");
  
  Console.WriteLine("模型文件:"+ _modelPath);
  
  5.  輸入一個測試數據,進行預測。
  
  輸入一個測試數據,使用生成的模型,進行預測
  
  var predictor = mlContext.Model.CreatePredictionEngine<IrisData, ClusterPrediction>(model);
  
  var Setosa = new IrisData
  
  {
  
  SepalLength = 5.1f,
  
  SepalWidth = 3.5f,
  
  PetalLength = 1.4f,
  
  PetalWidth = 0.2f
  
  };
  
  var prediction = predictor.Predict(Setosa);
  
  Console.WriteLine($"Cluster:www.zzxcscl.com {prediction.PredictedClusterId}");
  
  Console.WriteLine($"Distances: {string.Join(" ", prediction.Distances)}");
  
  Console.WriteLine("Press any key!");
  
  所有的代碼:
  
  複製代碼
  
  1 using Microsoft.ML;
  
  2 using System;
  
  3 using System.IO;
  
  4
  
  5 namespace KMeansDemo
  
  6 {
  
  7     class Program
  
  8     {
  
  9         static readonly string _dataPath = Path.Combine(Environment.CurrentDirectory, "Data", "iris.data");
  
  10         static readonly string www.dfyLhyni.com _modelPath = Path.Combine(Environment.CurrentDirectory, "Data", "IrisClusteringModel.zip");
  
  11
  
  12         static void Main(string[] args)
  
  13         {
  
  14             var mlContext = new MLContext(seed: 0);
  
  15             IDataView dataView = mlContext.Data.LoadFromTextFile<IrisData>(_dataPath, hasHeader: false, separatorChar: ',');
  
  16             string featuresColumnName = "Features";
  
  17             var pipeline = mlContext.Transforms
  
  18                 .Concatenate(featuresColumnName, "SepalLength", "SepalWidth", "PetalLength", "PetalWidth")
  
  19                 .Append(mlContext.Clustering.Trainers.KMeans(featuresColumnName, numberOfClusters: 3));
  
  20             var model = pipeline.Fit(dataView);
  
  21             using (var fileStream = new FileStream(www.kunLunyuLegw.com_modelPath, FileMode.Create, FileAccess.Write, FileShare.Write))
  
  22             {
  
  23                 mlContext.Model.Save(model, dataView.Schema, fileStream);
  
  複製代碼
  
  第二步,須要建立一個「數據源」用以指向存儲帳號下的具體容器,並指定數據源的類型。這裏會用到第一步建立的credential:
  
  複製代碼
  
  CREATE EXTERNAL DATA SOURCE CloudpickerStorage_SampleData
  
  WITH
  
  (    LOCATION   = 'wasbs://www.xingyunylpt.com  sampledata@cloudpickersa.blob.core.windows.net/'
  
  ,    CREDENTIAL = CloudpickerCredential
  
  ,    TYPE       = HADOOP
  
  );
  
  複製代碼
  
  這裏的參數"TYPE=HADOOP"其實回味無窮,由於咱們實際要鏈接的是Azure Blob Storage,而非HDFS。這隱含地說明PolyBase事實上是先支持Hadoop,後來才把Azure存儲以一種HDFS兼容的方式加入了支持。LOCATION中使用的wasb協議也印證了這一點,由於wasb原本就用於讓Azure Blob存儲掛載和融入到Hadoop體系中。
  
  第三步,則是先定義數據格式,而後終於能夠建立外部表並指向具體的csv文件。這裏會用到第二步建立的數據源:
  
  複製代碼
  
  CREATE EXTERNAL FILE FORMAT MyFileFormat_CSV
  
  WITH (FORMAT_TYPE = DELIMITEDTEXT,
  
  FORMAT_OPTIONS(
  
  FIELD_TERMINATOR www.zbyl2019.com= ',',
  
  FIRST_ROW = 2,
  
  USE_TYPE_DEFAULT = False)
  
  );
  
  CREATE EXTERNAL TABLE credit_card_loans(
  
  "year" INT,
  
  periodicity VARCHAR(20),
  
  "quarter" VARCHAR(20),
  
  load_type VARCHAR(MAX),
  
  loan_value DECIMAL(20,8)
  
  )
  
  WITH (
  
  LOCATION=www.senta7pt.com '/credit_card_loans.csv',
  
  DATA_SOURCE = CloudpickerStorage_SampleData,
  
  FILE_FORMAT = MyFileFormat_CSV
  
  )
  
  ;
  
  複製代碼
  
  這纔算是大功告成。能夠看到,在PolyBase中須要層層遞進地建立憑據、數據源、外部表這些重要實體,這是與嚴謹的SQL Server/T-SQL抽象體系相對應的。
  
  咱們火燒眉毛地來嘗試一下外部表訪問csv的效果。先作一個簡單的計數:
  
  嗯,頗爲順暢。再來一個與前篇文章相同的查詢,此次使用T-SQL來表達:
  
  也很快地返回了正確的結果。關於PolyBase的查詢性能,因爲牽涉到的因素會比較多,須要專題探討,在此不做重點討論。就這裏的例子而言,第一次的冷查詢會相對較慢,以後對同一外部表的各類查詢就比較快了,能夠秒級返回。
  
  至此,咱們已完整地使用Azure SQL DW中的PolyBase能力實現了對Blob Storage的即席查詢,實現了與前文例子中相同的效果。
  
  小結
  
  來自關係型數據庫世界的PolyBase,賦能用戶使用T-SQL直接訪問查詢Azure雲存儲中的數據文件,可謂神奇。這也許乍一聽上去是「曲線救國」,但真正實操下來其實至關方便,圓滿完成了面向雲存儲的交互式查詢的既定任務。
  
  在PolyBase的幫助下,開發者和數據分析師們能夠經過熟悉的SSMS或Azure Data Studio等客戶端工具隨時鏈接和查詢雲上大數據了。若是再考慮到SQL Server體系中ADO.NET/JDBC/ODBC等方便而成熟的訪問接口,PolyBase還不失爲一個生產應用集成雲上大數據的優美方式,既可用於數據搬運,也可直查數據湖。PolyBase對於調用方而言也較爲友好,由於訪問外部表和普通的內部數據表並沒有二致,間接實現了異構數據源的統一封裝和訪問。
  
  在本系列文章中,ADLA和PolyBase都已分別登場,各自展示了不遜於Athena的特色和能力。但在Azure上還有第三個選項,一樣具有很強的競爭力,咱們留待下回分解。windows

相關文章
相關標籤/搜索