SE の雑記

SQL Server の情報をメインに Microsoft 製品の勉強内容を日々投稿

SQL Server 2019 の PolyBase とリンクサーバーの違いについて

leave a comment

SQL Server 2019 では PolyBase の機能が進化し「データ仮想化」が一つのキーワードとなっています。

PolyBase は、SQL Server 2016 から実装された機能だったはずですが、SQL Server 2016 / 2017 では、Hadoop と Azure BLOB Storage の接続のみをサポートしており、オブジェクトストレージ上のデータに対してクエリを実行するための機能としての利用でした。

SQL Server 2019 になり、オブジェクトストレージの他に「ODBC 汎用コネクタ」がサポートされるようになり、アクセスできるデータソースが大幅に増加しました。

標準で、SQL Server / Oracle / Teradata / MongoDB へのアクセスもできるようになっているのですが、これらについては、「標準で導入されている ODBC ドライバー」となっており、実装については ODBC と同様です。
SQL Server 2019 のセミナーを毎月実施させていただいている中で「PolyBase とリンクサーバーの違い」について質問されることがあります。
これらの違いについては、次のドキュメントで解説が行われています。


リンクサーバーは ODBC をサポートしてないのですが、OLE DB Provider for ODBC という形で、ODBC ドライバーを利用することができましたので、これにより、他のデータソースをリンクサーバーとして設定することができました。
リンクサーバーではなく、OPENRWSET を使用して外部データソースに接続するケースもあったのではないでしょうか。
SQL Server 2019 については、ODBC でのアクセスとなりますので、OLE DB を介すことなく、直接 ODBC ドライバーを利用することになり、データソースに対しては、外部データソース / 外部テーブルを介して、アクセスすることになりますので、構文はシンプルなものとなっています。
冒頭で紹介した FAQ のドキュメントで、さらに細かな比較が行われています。

image

PolyBase の大きな特徴としては、次のようなものがあります。

  • データベーススコープのオブジェクトとして登録される
    • これにより AlwaysOn 可用性グループの複製対象となる、ユーザーデータベースのバックアップに情報が含まれる
    • PolyBase の場合、テーブル単位で設定をする必要があるので、手間はかかるのですが…。
  • ODBC ドライバーの利用
    • ユーザーがインストールした ODBC ドライバーについては 2019/5/6 時点では Windows のみ利用可能な機能となっており、SQL Server on Linux (SoL) / Big Data Cluster (BDC) では利用できません。
      SoL / BDC については、投稿を書いている時点では、標準で含まれている ODBC ドライバーのみ利用可能です。
  • 読み取りのみ可能
      • リンクサーバーは読み取り / 更新が可能ですが、PolyBase については、基本的に読み取り専用となります。
        (Hadoop / BDC の Data Pool については書き込みができますがそれ以外は読み取り専用です)
  • クエリの実行環境をスケールアウトさせることができる
    • リンクサーバーは、設定した SQL Server での実行となりますが、PolyBase については、Enterprise Edition を使用している場合 スケールアウト環境 として構築することができます。

PolyBase も リンクサーバーも、データソースからのデータ取得のコストを減らすために、データソースから、データを取得する際に、ソースでデータを減らして取得する、プッシュダウン が行われるようになっており、これは PolyBase でODBC データソースを使用した場合も同様です。
本投稿で書いた違い以外については、Frequently asked questions を一読すると全体像を把握できるのではないでしょうか。
PolyBase のメリットである「読み取りスケールアウトなクエリ」については 1 点注意点がありますので、以下の内容も併せて確認をして下さい。
 
PolyBase の読み取りスケールアウトなクエリ実行時の注意点
PolyBase を利用した場合はスケールアウトができるというメリットがあり、これが大きな特徴として挙げられます。
スケールアウトについてですが、一つ注意点があります。
スケールアウトの考え方には、2 種類あるかと思います。

  1. 各クエリを実行する環境を分散させることでスケールアウトさせる (分散したクエリ処理)
  2. 一つのクエリの実行を分散させることでスケールアウトさせる (スケールアウトな読み取り)

スケールアウトというと、ある、一つのクエリを実行した際にそのクエリの処理を複数のサーバーに分散させて実行するというケースを思い浮かべるかもしれませんが、RDBMS をデータソースとして使用して、一つのクエリをチャンクして実行する スケールアウト読み取り については、条件があります。
現時点では、単一のクエリの実行を複数のサーバーに分割して実行するためには、次の条件を満たす必要があります。

  • SQL Server / Oracle / TeraData を使用
  • 上記のデータベースで参照テーブルがパーティショニングされている

この条件を満たしている場合「一つのクエリの実行を複数のサーバーで分散して実行」することが可能となります。
外部データソースを SQL Server にして確認をしてみたところ、スケールアウトグループで実行を行うと、最初に次のようなクエリが実行されています。

SELECT
            PARTITION_FUNCTIONS.name, QUOTENAME(COLUMNS.name), cast(PARTITIONS.partition_number AS nvarchar(10))
          FROM
            "tpch".sys.indexes AS INDEXES,
            "tpch".sys.partitions AS PARTITIONS,
            "tpch".sys.index_columns AS INDEX_COLUMNS,
            "tpch".sys.columns AS COLUMNS,
            "tpch".sys.partition_functions AS PARTITION_FUNCTIONS,
            "tpch".sys.partition_schemes AS PARTITION_SCHEMES
          WHERE
            -- Match the table's object_id.
            INDEXES.object_id = object_id('tpch.dbo.ORDERS') AND
            -- Ensure it is either a heap or a clustered index.
            INDEXES.type IN (0,1,5) AND
            -- Ensure it is a partitioning column.
            INDEX_COLUMNS.partition_ordinal = 1 AND
            -- INDEXES join PARTITIONS
            INDEXES.object_id = PARTITIONS.object_id AND
            INDEXES.index_id = PARTITIONS.index_id AND
            -- INDEXES join INDEX_COLUMNS
            INDEXES.object_id = INDEX_COLUMNS.object_id AND
            INDEXES.index_id = INDEX_COLUMNS.index_id AND
            -- INDEXES join PARTITION_SCHEMES
            INDEXES.data_space_id = PARTITION_SCHEMES.data_space_id AND
            -- PARTITION_SCHEMES join PARTITION_FUNCTIONS
            PARTITION_SCHEMES.function_id = PARTITION_FUNCTIONS.function_id AND
            -- INDEX_COLUMNS join COLUMNS
            INDEXES.object_id = COLUMNS.object_id AND
            INDEX_COLUMNS.column_id = COLUMNS.column_id

 
パーティションの情報の取得が行われていますね。

これにより、「パーティション単位でクエリ実行元のサーバーを分散させる」という動作になります。
実際に実行されているクエリが次のものになるのですが、複数のサーバーからクエリが実行されていますが、「$partition」を使用して各サーバーがアクセスするパーティションが分散されていることが確認できます。
image

Share

Written by Masayuki.Ozawa

5月 6th, 2019 at 7:40 pm

Posted in SQL Server

Tagged with ,

Leave a Reply