XMLA エンドポイントを使用した高度な増分更新およびリアルタイム データ

読み取りと書き込みの操作に対して XMLA エンドポイントが有効になっている Premium 容量のセマンティック モデルでは、ツール、スクリプト、API のサポートを通じて、より高度な更新、パーティション管理、メタデータのみのデプロイが可能です。 さらに、XMLA エンドポイントを使用した更新操作は 1 日 48 回の更新に制限されず、スケジュールされた更新の制限時間も課されません。

メジャー グループ

セマンティック モデル テーブルのパーティションは表示されず、Power BI Desktop や Power BI サービスを使って管理できません。 Premium 容量に割り当てられたワークスペース内のモデルの場合は、XMLA エンドポイントを介してパーティションを管理できます。これには、SQL Server Management Studio (SSMS)、オープンソースの表形式エディター、表形式モデルのスクリプト言語 (TMSL) を使ったスクリプト、表形式オブジェクト モデル (TOM) を使うプログラムなどのツールを使います。

モデルを Power BI サービスに初めて発行すると、新しいモデル内の各テーブルにパーティションが 1 つ作成されます。 増分更新ポリシーのないテーブルの場合、その 1 つのパーティションには、そのテーブルのすべてのデータの行が格納されます (フィルターが適用されていない限り)。 増分更新ポリシーがあるテーブルの場合は、ポリシーが Power BI によってまだ適用されていないため、その 1 つの初期パーティションだけが存在します。 初期パーティションは、Power BI Desktop で、RangeStart および RangeEnd パラメーターに基づくテーブルの日付/時刻範囲フィルター、および Power Query エディターで適用されるその他のフィルターを定義するときに構成します。 この初期パーティションには、使用するフィルター条件を満たすデータ行のみが含まれます。

"最初" の更新操作を実行すると、増分更新ポリシーが指定されていないテーブルでは、そのテーブルの既定の単一パーティションに含まれるすべての行が更新されます。 増分更新ポリシーのあるテーブルの場合は、更新および履歴パーティションが自動的に作成され、各行の日付/時刻に従って行が読み込まれます。 増分更新ポリシーにデータをリアルタイムで取得する方法が含まれている場合、Power BI では、DirectQuery パーティションもテーブルに追加します。

この最初の更新操作は、データ ソースから読み込む必要のあるデータの量によっては、かなり時間がかかることがあります。 また、更新操作では追加の処理と再計算を実行する必要があるため、モデルの複雑さも重要な要因になる可能性があります。 この操作はブートストラップすることができます。 詳しくは、「最初の完全な更新でタイムアウトを回避する」を参照してください。

パーティションは、期間の単位 (年、四半期、月、日) ごとに作成されて名前が付けられます。 最新のパーティションである "更新" パーティションには、ポリシーで指定した更新期間内の行が含まれます。 履歴パーティションには、更新期間までの完了期間ごとの行が格納されます。 リアル タイムが有効になっている場合、DirectQuery パーティションでは、更新期間の終了日以降に発生したデータの変更も取得します。 更新と履歴のパーティションの単位は、ポリシーを定義するときに選択した更新と履歴 (保存) の期間によって異なります。

たとえば、今日の日付は 2021 年 2 月 2 日で、データ ソースの FactInternetSales テーブルには今日までの行が含まれており、またポリシーで、リアルタイムの変更を含めること、過去 1 日間の更新期間内の行を更新すること、過去 3 年間の履歴期間内の行を格納することが指定されているとします。 その場合、最初の更新操作では、今後の変更用に DirectQuery パーティションが作成され、今日の行のために新しいインポート パーティションが作成され、昨日 (2021 年 2 月 1 日) の丸 1 日の期間ために履歴パーティションが作成されます。 前の丸 1 か月の期間 (2021 年 1 月) の履歴パーティションが作成され、前の丸 1 年の期間 (2020 年) の履歴パーティションが作成され、2019 年と 2018 年の丸 1 年の期間の履歴パーティションが作成されます。 2021 年の最初の四半期はまだ完了していないので、四半期全体のパーティションは作成されません。

Diagram shows the partition naming granularity described in the text.

各更新操作が行われると、更新期間パーティションだけが更新され、DirectQuery パーティションの日付フィルターは、現在の更新期間の後に発生する変更のみを含めるように更新されます。 更新された更新期間内に新しい日付/時刻の新しい行に対して新しい更新パーティションが作成され、更新期間内の既存のパーティション内に既に日付/時刻がある既存の行が更新内容で更新されます。 更新期間よりも古い日付/時刻を含む行は、更新されなくなります。

期間全体が終了すると、パーティションがマージされます。 たとえば、ポリシーに 1 日の更新期間と 3 年間の履歴保存期間が指定されている場合、その月の最初の日に、前月のすべての日パーティションが月パーティションにマージされます。 新しい四半期の最初の日に、前の 3 つのすべての月パーティションが四半期パーティションにマージされます。 新しい年の最初の日に、前の 4 つのすべての四半期パーティションが年パーティションにマージされます。

モデルには、常に、過去の保存期間全体に対するパーティションに加えて、現在の更新期間までの期間全体のパーティションが保持されます。 この例では、丸 3 年間の履歴データが 2018 年、2019 年、2020 年のパーティションに保持され、2021Q101 の月期、2021Q10201 の日期、および現在の日付の更新期間のパーティションにも保持されます。 この例では 3 "" 間の履歴データを保持するので、2018 パーティションは 2022 年 1 月 1 日の最初の更新まで保持されます。

Power BI 増分更新およびリアルタイム データを使用すると、ポリシーに基づいてパーティション管理がサービスによって処理されます。 パーティション管理はすべてサービスで処理できますが、XMLA エンドポイントを介してツールを使用すると、パーティションを個別に、順番に、または並行して、選択的に更新できます。

SQL Server Management Studio を使用した更新管理

SQL Server Management Studio (SSMS) を使用して、増分更新ポリシーの適用によって生成されたパーティションを表示および管理することができます。 SSMS を使用すると、たとえば、増分更新期間内にない特定の履歴パーティションを更新することで、日付を遡って更新を実行することができます。すべての履歴データを最新の情報に更新する必要はありません。 また、履歴パーティションを一括で増分的に追加または更新することで、大きなモデルの履歴データの読み込みをブートストラップするときにも、SSMS を使用できます。

Screenshot shows the Partitions window in SSMS.

増分更新の動作をオーバーライドする

SSMS では、表形式モデルのスクリプト言語表形式オブジェクト モデルを使用して、更新を呼び出す方法をより細かく制御することもできます。 たとえば、SSMS では、オブジェクト エクスプローラーでテーブルを右クリックし、[テーブルの処理] メニュー オプションを選択してから、[スクリプト] ボタンを選択して TMSL 更新コマンドを生成します。

Screenshot shows the Script button in Process Table dialog.

次のパラメーターを TMSL 更新コマンドで使用して、既定の増分更新動作をオーバーライドすることができます。

  • applyRefreshPolicy。 テーブルに増分更新ポリシーが定義されている場合、applyRefreshPolicy によってポリシーが適用されるかどうかを決定します。 ポリシーが適用されない場合、完全処理操作では、パーティション定義は変わらないままで、テーブル内のすべてのパーティションは完全に更新されます。 既定値は true です。

  • effectiveDate。 増分更新ポリシーが適用されている場合は、増分更新および履歴期間に対するローリング ウィンドウ範囲を決定するために、現在の日付が認識されている必要があります。 effectiveDate パラメーターを使用すると、現在の日付をオーバーライドすることができます。 このパラメーターは、データを過去または将来の日付まで増分更新するテスト、デモ、およびビジネスのシナリオにおいて役立ちます (たとえば、将来の予算など)。 既定値は現在の日付です。

{ 
  "refresh": {
    "type": "full",

    "applyRefreshPolicy": true,
    "effectiveDate": "12/31/2013",

    "objects": [
      {
        "database": "IR_AdventureWorks", 
        "table": "FactInternetSales" 
      }
    ]
  }
}

TMSL での既定の増分更新動作の上書きの詳細については、「Refresh コマンド」を参照してください。

最適なパフォーマンスの確保

Power BI サービスでは、更新操作のたびに、データ ソースに初期化クエリを送信して各増分更新パーティションを確保することができます。 次の構成を確実に行って初期化クエリの数を減らすことで、増分更新のパフォーマンスの向上を実現できる場合があります。

  • 増分更新を構成するテーブルには、1 つのデータ ソースからデータを取得する必要があります。 テーブルに複数のデータ ソースからデータが取得されると、更新操作ごとにサービスによって送信されるクエリの数にデータ ソースの数が乗算されるので、更新のパフォーマンスが低下する可能性があります。 増分更新テーブルのクエリは、1 つのデータ ソースを対象にするようにします。
  • インポート パーティションの増分更新と直接クエリを使用したリアルタイム データの両方を含むソリューションの場合、すべてのパーティションで 1 つのデータ ソースのデータに対してクエリを実行する必要があります。
  • ご利用のセキュリティ要件で許可されている場合は、[データ ソースのプライバシー レベル] 設定を [組織] または [パブリック] に設定します。 既定では、プライバシー レベルは [プライベート] になっています。しかし、このレベルだと、他のクラウド ソースとのデータの交換が阻止される可能性があります。 プライバシー レベルを設定するには、[その他のオプション] メニューを選択し、[設定]>[データ ソースの資格情報]>[資格情報の編集]>[このデータ ソースのプライバシー レベルの設定] の順に選択します。 サービスへの発行前に Power BI Desktop モデルでプライバシー レベルが設定されている場合、発行時にそれはサービスに転送されません。 その場合でも、サービスのセマンティック モデルの設定で、それを設定する必要があります。 詳細については、プライバシー レベルに関するページを参照してください。
  • オンプレミスのデータ ゲートウェイを使用している場合は、必ずバージョン 3000.77.3 以上を使用してください。

最初の完全な更新でタイムアウトを回避する

Power BI サービスへの発行後、モデルの最初の完全な更新操作によって増分更新テーブルのパーティションが作成され、増分更新ポリシーで定義された期間全体の履歴データが読み込まれて処理されます。 大量のデータを読み込んで処理する一部のモデルでは、最初の更新操作にかかる時間が、サービスで設けられている更新の時間制限やデータ ソースで設けられているクエリの時間制限を超えることがあります。

最初の更新操作をブートストラップすると、サービスで増分更新テーブルのパーティション オブジェクトを作成できますが、履歴データをパーティションに読み込んで処理することはできません。 その後、SSMS を使用して、パーティションが選択的に処理されます。 各パーティションに読み込まれるデータの量に応じて、各パーティションを順番に、または小さいバッチで処理して、それらの 1 つまたは複数のパーティションでタイムアウトが発生する可能性を減らすことができます。 次の機能は、任意のデータ ソースに使用できます。

Apply Refresh Policy(更新ポリシーの適用)

オープンソースの Tabular Editor 2 ツールを使用すると、最初の更新操作を簡単にブートストラップできます。 増分更新ポリシーが定義されたモデルを Power BI Desktop からサービスに発行した後、XMLA エンドポイントを読み取り/書き込みモードで使用してモデルに接続します。 増分更新テーブルで、 [Apply Refresh Policy](更新ポリシーの適用) を実行します。 ポリシーを適用しただけでは、パーティションは作成されますが、データは読み込まれません。 次に、SSMS に接続して、データを読み込んで処理するために、パーティションを順番に、またはバッチで更新します。 詳しくは、Tabular Editor のドキュメントの「Incremental refresh (増分更新)」を参照してください。

Screenshot show the Tabular Editor with Apply Refresh Policy selected.

空のパーティションの Power Query フィルター

モデルをサービスに発行する前に、Power Query エディターで、0 以外の値を効果的に除外する、または FactInternetSales テーブルから "すべての" データを除外する、別のフィルターを ProductKey 列に追加します。

Screenshot shows the Power Query Editor with code that filters out the product key.

Power Query エディターで [閉じて適用] を選び、増分更新ポリシーを定義して、モデルを保存すると、モデルはサービスに発行されます。 サービスから、モデルに対して最初の更新操作が実行されます。 ポリシーに従って FactInternetSales テーブルのパーティションが作成されますが、すべてのデータが除外されているため、データが読み込まれて処理されることはありません。

最初の更新操作が完了した後、Power Query エディターに戻ると、ProductKey 列のもう一方のフィルターは削除されます。 Power Query エディターで [閉じて適用] を選んでモデルを保存した後は、モデルは "再発行できません"。 モデルがもう一度発行された場合、増分更新ポリシーの設定は上書きされ、その後で更新操作がサービスから実行されると、モデルの完全な更新が強制的に行われます。 代わりに、"モデル" から ProductKey 列のフィルターを削除するメタデータのみのデプロイを、アプリケーション ライフサイクル管理 (ALM) ツールキットを使って実行します。 その後、SSMS を使用して、パーティションを選択的に処理できます。 SSMS からすべてのパーティションが完全に処理されている場合 (すべてのパーティションでのプロセスの再計算が含まれる必要があります)、サービスからのモデルに対するその後の更新操作では、増分更新パーティションのみが更新されます。

ヒント

BI の専門家の Power BI のコミュニティによって提供されているビデオやブログなどを確認してください。

SSMS からのテーブルとパーティションの処理の詳細については、データベース、テーブル、またはパーティションの処理 (Analysis Services) に関するページを参照してください。 TMSL を使用したモデル、テーブル、パーティションの処理について詳しくは、「Refresh コマンド (TMSL)」をご覧ください。

データ変更の検出のためのカスタム クエリ

TMSL や TOM を使用して、検出されたデータ変更動作をオーバーライドできます。 この方法を使用すれば、メモリ内キャッシュでの最終更新列の永続化を回避できるだけでなく、更新が必要なパーティションのみにフラグを付けるために、抽出、変換、読み込み (ETL) プロセスによって構成または命令テーブルが準備されるというシナリオを実現できます。 この方法により、データ更新がどれほど前に行われたかに関係なく、必要な期間についてのみ更新されるという、より効率的な増分更新プロセスを作成できます。

pollingExpression は、他の M クエリの簡易な M 式または名前とすることを目的としています。 スカラー値が返される必要があり、パーティションごとに実行されます。 返された値が、増分更新を最後に実行したときとは異なる場合、パーティションには完全処理のフラグが設定されます。

次の例では、日付を遡った変更について履歴の期間内の 120 か月すべてが対象とされています。 10 年ではなく 120 か月を指定した場合、データ圧縮はそれほど効率的ではないかもしれませんが、履歴年の 1 年全体を更新する必要はなくなります (その場合、日付を遡った変更に対して 1 か月で十分であるときに、よりコストがかかります)。

"refreshPolicy": {
    "policyType": "basic",
    "rollingWindowGranularity": "month",
    "rollingWindowPeriods": 120,
    "incrementalGranularity": "month",
    "incrementalPeriods": 120,
    "pollingExpression": "<M expression or name of custom polling query>",
    "sourceExpression": [
    "let ..."
    ]
}

ヒント

BI の専門家の Power BI のコミュニティによって提供されているビデオやブログなどを確認してください。

メタデータのみの配置

新しいバージョンの .pbix ファイルを Power BI Desktop からワークスペースに発行すると、同じ名前を持つモデルが既に存在している場合、既存のモデルの置き換えの確認を求められます。

Screenshot shows the Replace model dialog.

場合によっては、モデルを置き換えたくないことがあります (特に増分更新の場合)。 Power BI Desktop でのモデルは、Power BI サービスでのものより大幅に小さくなる可能性があります。 Power BI サービス内のモデルに増分更新ポリシーが適用されている場合、モデルが置き換えられると失われる、数年分の履歴データが含まれている可能性があります。 すべての履歴データを最新の情報に更新すると、時間がかかり、ユーザーに対してシステムのダウンタイムが発生する可能性があります。

代わりに、メタデータのみの配置を実行することをお勧めします。これにより、履歴データを失うことなく新しいオブジェクトを配置できます。 たとえば、いくつかのメジャーを追加した場合、データを更新する必要なく新しいメジャーのみを展開できるので、時間を節約できます。

XMLA エンドポイントの読み取り/書き込み用に構成された Premium 容量に割り当てられたワークスペースでは、互換性のあるツールによってメタデータのみの配置を実現できます。 たとえば、ALM Toolkit は Power BI モデル用のスキーマ差分ツールであり、これを使ってメタデータのみのデプロイを実行できます。

Analysis Services の Git リポジトリから最新バージョンの ALM Toolkit をダウンロードしてインストールします。 ALM Toolkit の使用に関するステップバイステップのガイダンスは、Microsoft のドキュメントには含まれていません。 ALM Toolkit のドキュメントへのリンクと、サポートの可否に関する情報には、[ヘルプ] リボンでアクセスできます。 メタデータのみのデプロイを実行するには、比較を実行し、実行中の Power BI Desktop インスタンスをソースとして選び、Power BI サービス内の既存のモデルをターゲットとして選びます。 表示される相違点を検討し、テーブルと増分更新パーティションの更新をスキップするか、[オプション] ダイアログを使用してテーブルの更新のためにパーティションを維持します。 選択内容を検証してターゲット モデルの整合性を確保してから、更新を行います。

Screenshot shows the ALM Toolkit window.

増分更新ポリシーとリアルタイム データをプログラムで追加する

TMSL と TOM を使って、XMLA エンドポイントを介して既存のモデルに増分更新ポリシーを追加することもできます。

Note

互換性の問題を回避するには、Analysis Services クライアント ライブラリの最新バージョンを必ず使用してください。 たとえば、ハイブリッド ポリシーを使用するには、バージョンが 19.27.1.8 以上である必要があります。

このプロセスには、次の手順が含まれます。

  1. ターゲット モデルが最低限必要な互換性レベルであることを確認します。 SSMS で、[モデル名]>を右クリックして>、[プロパティ][互換性レベル] を選びます。 互換性レベルを引き上げるには、createOrReplace TMSL スクリプトを使用するか、例として挙げた次の TOM サンプル コードを確認してください。

    a. Import policy - 1550
    b. Hybrid policy - 1565
    
  2. モデルの式に RangeStartRangeEnd パラメーターを追加します。 必要に応じて、日付/時刻の値を日付キーに変換する関数も追加します。

  3. 必要とするアーカイブ (ローリング ウィンドウ) および増分更新期間と、RangeStart および RangeEnd パラメーターに基づいてターゲット テーブルをフィルター処理するソース式とを使用して、RefreshPolicy オブジェクトを定義します。 自分のリアルタイム データ要件に応じて、更新ポリシー モードを [インポート] または [ハイブリッド] に設定します。 [ハイブリッド] の場合、Power BI では、最終更新時刻の後に発生した最新の変更をデータ ソースから取り込むために、DirectQuery パーティションをテーブルに追加します。

  4. 要件に従いテーブルが Power BI によってパーティション分割されるように、更新ポリシーをテーブルに追加し、完全な更新を実行します。

次のコード サンプルは、TOM を使用して上記の手順を行う方法を示しています。 このサンプルをそのまま使う場合は、AdventureWorksDW データベースのコピーを作成し、FactInternetSales テーブルをモデルにインポートする必要があります。 このコード サンプルでは、RangeStart および RangeEnd パラメーターと DateKey 関数がモデル内に存在していないものと想定しています。 単に FactInternetSales テーブルをインポートし、モデルを Power BI Premium 上のワークスペースに発行します。 次に、コード サンプルがモデルに接続できるように workspaceUrl を更新します。 必要に応じて、他のコード行も更新してください。

using System;
using TOM = Microsoft.AnalysisServices.Tabular;
namespace Hybrid_Tables
{
    class Program
    {
        static string workspaceUrl = "<Enter your Workspace URL here>";
        static string databaseName = "AdventureWorks";
        static string tableName = "FactInternetSales";
        static void Main(string[] args)
        {
            using (var server = new TOM.Server())
            {
                // Connect to the dataset.
                server.Connect(workspaceUrl);
                TOM.Database database = server.Databases.FindByName(databaseName);
                if (database == null)
                {
                    throw new ApplicationException("Database cannot be found!");
                }
                if(database.CompatibilityLevel < 1565)
                {
                    database.CompatibilityLevel = 1565;
                    database.Update();
                }
                TOM.Model model = database.Model;
                // Add RangeStart, RangeEnd, and DateKey function.
                model.Expressions.Add(new TOM.NamedExpression {
                    Name = "RangeStart",
                    Kind = TOM.ExpressionKind.M,
                    Expression = "#datetime(2021, 12, 30, 0, 0, 0) meta [IsParameterQuery=true, Type=\"DateTime\", IsParameterQueryRequired=true]"
                });
                model.Expressions.Add(new TOM.NamedExpression
                {
                    Name = "RangeEnd",
                    Kind = TOM.ExpressionKind.M,
                    Expression = "#datetime(2021, 12, 31, 0, 0, 0) meta [IsParameterQuery=true, Type=\"DateTime\", IsParameterQueryRequired=true]"
                });
                model.Expressions.Add(new TOM.NamedExpression
                {
                    Name = "DateKey",
                    Kind = TOM.ExpressionKind.M,
                    Expression =
                        "let\n" +
                        "    Source = (x as datetime) => Date.Year(x)*10000 + Date.Month(x)*100 + Date.Day(x)\n" +
                        "in\n" +
                        "    Source"
                });
                // Apply a RefreshPolicy with Real-Time to the target table.
                TOM.Table salesTable = model.Tables[tableName];
                TOM.RefreshPolicy hybridPolicy = new TOM.BasicRefreshPolicy
                {
                    Mode = TOM.RefreshPolicyMode.Hybrid,
                    IncrementalPeriodsOffset = -1,
                    RollingWindowPeriods = 1,
                    RollingWindowGranularity = TOM.RefreshGranularityType.Year,
                    IncrementalPeriods = 1,
                    IncrementalGranularity = TOM.RefreshGranularityType.Day,
                    SourceExpression =
                        "let\n" +
                        "    Source = Sql.Database(\"demopm.database.windows.net\", \"AdventureWorksDW\"),\n" +
                        "    dbo_FactInternetSales = Source{[Schema=\"dbo\",Item=\"FactInternetSales\"]}[Data],\n" +
                        "    #\"Filtered Rows\" = Table.SelectRows(dbo_FactInternetSales, each [OrderDateKey] >= DateKey(RangeStart) and [OrderDateKey] < DateKey(RangeEnd))\n" +
                        "in\n" +
                        "    #\"Filtered Rows\""
                };
                salesTable.RefreshPolicy = hybridPolicy;
                model.RequestRefresh(TOM.RefreshType.Full);
                model.SaveChanges();
            }
            Console.WriteLine("{0}{1}", Environment.NewLine, "Press [Enter] to exit...");
            Console.ReadLine();
        }
    }
}