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 のドキュメントで、さらに細かな比較が行われています。
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 種類あるかと思います。
- 各クエリを実行する環境を分散させることでスケールアウトさせる (分散したクエリ処理)
- 一つのクエリの実行を分散させることでスケールアウトさせる (スケールアウトな読み取り)
スケールアウトというと、ある、一つのクエリを実行した際にそのクエリの処理を複数のサーバーに分散させて実行するというケースを思い浮かべるかもしれませんが、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」を使用して各サーバーがアクセスするパーティションが分散されていることが確認できます。