テクテク日記

テクテク=テクノロジー&一歩ずつ(テクテク)https://aka.ms/techtech2 より、カテゴリー別にフィルターできるようになります。

Power BI レポート最適化の実践Tips

前回はスタースキーマを使用した場合にレポートのパフォーマンスがかえって悪化するという、特殊な事例をご紹介しました。今回はその続編として、「クエリ最適化・ドリルスルー・ビジュアルの制限・削減による実践的アプローチ」を実践することで、レポートのパフォーマンスをさらに改善するためのコツについてご紹介します。

今回のテーマは、以下の 3 点です:

  1. 高カーディナリティ時のDAX メジャーの作成
  2. Query Reduction(クエリの削減)設定の活用
  3. ドリルスルーの活用によるパフォーマンス制御

今回ご紹介する内容は、全体として「気を付けるべきポイント」や「実践的なTips」の紹介となりますが、特にデータ量の多いレポートを作成する際に有効なベストプラクティスでもあります。実際のレポート設計やチューニング時にぜひ念頭に置いていただければと思います。
※注:本ブログでは説明に多数の GIF 動画を使用しています。ネットワーク速度が遅い環境では、GIF の読み込みに時間がかかる場合があります。

Power BI におけるパフォーマンスの基本原則

Power BI の応答速度は、主に次の 3 要素に影響されます。

  • データモデルの設計(モデリング効率)
    • スタースキーマや適切な列削減による VertiPaq 圧縮効率の最適化
    • 高カーディナリティ列の扱い方(スタースキーマでなくても良い特殊事例)
  • DAX クエリの効率(FE / SE バランス)
    • Storage Engine に処理を押し込み、Formula Engine の負荷を最小化
  • レポート設計(クエリの発行回数と負荷のコントロール
    • 不要なクエリや再計算を減らす
    • ユーザーの操作フローに応じた情報提示
    • 不要なビジュアルの排除

今回紹介する 3 つの手法は、特にレポート設計 の領域に属します。モデルやDAXを大きく変更できない場合でも、レポートページやビジュアル設計を見直すことで、体感速度を大きく改善できます。

1. 高カーディナリティ時のDAX メジャーの作成

レポート設計の話に入る前に、まず重要な点をお伝えします。今回のサンプルモデル作成中に DAX メジャーを構築しようとしたところ、下記画像のように「処理中です」の表示が延々と続き、メジャーを記述できるようになるまで異常に時間がかかり、Power BI Desktop の動作が極端に遅くなりました。

同じ行数(例:1億行)でも、商品や顧客などユニークレコードが数百万に及ぶ高カーディナリティ(高一意値)のデータセットでは、DAX メジャーの作成前後で Power BI Desktop のレンダリングや応答が著しく重くなることがあります。特に、他のアプリケーションを同時に起動している場合は、PC のスペックによってこの現象が発生しやすくなります。

ただし、必ずしも常に再現できるわけではなく、おそらく負荷の高い処理を行っていたために、メモリおよび CPU 使用率が上昇していた可能性もあります。こうした場合の最も効果的な対策は、カーディナリティを下げた状態で DAX メジャーを作成することです。特に、DAX メジャーの構築やレポートの完成前で、これから仕上げていく段階では有効です。

例えば、商品テーブル (DimProduct) と売上テーブル (Sales) のモデルがあり、商品テーブルに400 万レコードのレコードが存在する場合、インポートモデルでの読み込みを 1 万行に制限し、その状態でまず DAX メジャーを作成してから本番データに適用する方法が最適でしょう。

なお、既にメジャーが作られていた場合、一般的にメジャーを編集すると、その瞬間にレポート上のすべてのビジュアルが再評価され(=バックグラウンドでクエリが実行され)、再描画が重いページでは入力まで“待たされる”ことが原因となる場合があります。

この改善として、以下いずれかのワークアラウンドを試すことで改善が期待できます。

  • 編集前に [最適化] → [ビジュアルの一時停止] (Pause visuals) をONにし、DAXメジャーを記述していく

    これを実施する前後の比較動画は以下の通りです。ご覧の通り、DAX メジャーを作成しようとした瞬間に、すべてのビジュアルが更新されていることが確認できます。

    一方、下記のように「ビジュアルの一時停止」を有効にしてから DAX メジャーを作成すると、描画が必要なビジュアルから DAX クエリが発行されずに済むため、メジャー作成時の操作性が向上します。

  • 空のページ(または軽い検証用ページ)に切り替えてからメジャーを記述
    こちらのやり方は何もないページでDAXメジャーを作ることになるため、操作性が最も優れていると言えるでしょう
  • モデル ビューでメジャーを記述(レポート キャンバスの再描画を避ける)
    「空のページ」同様、有効なやり方の1つとなります

「ビジュアルがあるページを避ける」というのが最も確実な方法ですが、多くの DAX メジャーを作成する必要がある場合は、TMDL View(過去記事)を活用するのも有効です。下記の動画では、選択範囲を Shift + Alt + ↓ の同時押しで簡単に複製し、類似メジャーを瞬時に作成する方法を紹介しています。

これ以外にも、サードパーティーツールである Tabular Editor を利用する方法も便利です。Tabular Editor は、TMDL View と同様に Power BI セマンティックモデルのメタデータを操作し、その変更内容をモデルへ書き戻すことができる生産性向上ツールであり、Power BI のモデル開発において最も広く利用されている外部ツールの一つです。下記動画ではTabular Editor 2を開き、Countというメジャーを選択してCtrl + C → Ctrl +Vでメジャーを複製しているシーンとなります。

2. Query Reduction(クエリの削減)設定の活用

Power BI では、スライサーやフィルターを変更するたびに DAX クエリが発行されます。デフォルト設定では、ユーザーが1つの値を選択するたびに即座にクエリが再実行されるため、大量のスライサーを配置したページでは、不要な中間計算が頻発します。

「Query Reduction (クエリの削減) 設定」はDirectQuery 向けの機能ですが、Import モードでも利用できるため、ここで紹介します。これを有効化すると、フィルターやスライサーの操作が一時的にバッファリングされ、ユーザーが確定操作([適用] ボタン押下)を行った時点で、まとめてクエリを実行できます。

設定方法

以下のように操作します。なお、操作前のオプションは以下の通り。

  • Power BI Desktopの[最適化] → [最適化の事前設定] → [クエリを減らす] → [すべてのスライサーを適用ボタン]
  • ② をクリックすると、ポップアップが出現しますので、 [了解しました]をクリック
    同様に、③ をクリックすると、下図のようなオブジェクトが挿入されます。
  • [クエリを減らす]オプションを再度チェックすると、以下のようになっていることを確認できます。

ボタンの”お化粧”

これで準備が整いました。次に、[すべてのスライサーを適用] アイコンをクリックし、[ボタンのスタイル] 設定にある「既定」と「ポイントしたとき」のスタイルを変更します(下例参照)。

この設定はやや手間がかかり、慣れるまでに 10 分程度かかる場合があります。しかし、設定が完了すると、以下のようにスライサーを選択した際に該当オブジェクトがハイライト表示されるようになります(左が既定、右が変更後)。

効果確認

[すべてのスライサーを適用] ボタンは、スライサーで項目を選択し終えてボタンをクリックするまで、スライサー以外のビジュアルに対してクエリを発行しない最適化を行います。これにより、次のような課題を解消できます。

  • 不要なクエリ実行回数を大幅削減
  • 大量のスライサーを含むダッシュボードで特に有効
  • 複数条件を組み合わせて検索する際、都度待たされるストレスを解消

このように、調べたいコンテンツがある程度明確な場合は、スライサーを1つずつ選択して計3回 DAX クエリを発行するのではなく、1回の適用でまとめてクエリを発行できます。そのため、データ量が多いレポートやカーディナリティの高いレポートでも、よりリソースフレンドリーに動作します。

例えば、[すべてのスライサーを適用]が設定されている状態で、①~③まで選択した場合、クエリとして発行されたのはスライサーの選択のみとなります。

最初に発行された DAX クエリを確認すると、以下のような内容が返されました。これはチャートやテーブルビジュアルを描画するためのものではなく、あくまでスライサー選択時に発行されるクエリであり、パフォーマンス上のボトルネックにはなりません。

DAXクエリ: スライサーの選択

DEFINE
    VAR __DS0Core = 
        VALUES('Data'[ListingClassName])
    VAR __DS0PrimaryWindowed = 
        TOPN(101, __DS0Core, 'Data'[ListingClassName], 1)
EVALUATE
   __DS0PrimaryWindowed
ORDER BY
    'Data'[ListingClassName]

 [すべて適用] をクリックすると、下記のように 1 回だけ、すべてのビジュアルに対してクエリが発行されることが確認できます。

一方、通常の動作では、スライサーを選択するたびに各ビジュアルに対して DAX クエリが発行されるため、下図のように多くのクエリが発行されます。

インポートモデルの場合、クエリパフォーマンスが高速なため、この設定を行わなくても通常は大きな問題にはなりません。しかし、インポートモデルであっても、今回のような高カーディナリティモデルDirectQueryを使用するケースでは、このテクニックが特に有効です。

解除ボタンの設定

「すべて解除」ボタン(名称は適宜変更可)を設置し、解除操作ができるようにしておくのも有効でしょう

「すべて解除」は、ブックマークを使って初期状態に戻す「初期化」ボタンと似た動作をしますが、決定的な違いがあります。「初期化」ボタンは [すべてのスライサーを適用] をクリックした後でなければ初期化できませんが、「すべて解除」は途中まで選択した項目をその場で解除できます。

保留中のアイコンの設定

スライサーが多い場合、どのスライサーが選択されて「一括適用」の対象になっているかを見失うことがあります。そんなときに便利なのが 「保留中のアイコン」 の設定です。手順は以下のとおり。

  1. 該当スライサーを選択
  2. スライサーヘッダー保留中のアイコンカラー を変更

設定後は、途中まで選択したスライサーに赤いアイコンが表示されるようになり、一目で判別できるようになります。

「クエリの削減」の注意点

メリットが目立つ「クエリの削減」機能ですが、実はデメリットも存在します。

  • ユーザーが「適用」ボタンを押し忘れる可能性があるため、UI 説明やガイドが必要
  • 即時反映が望ましいフィルター(期間スライサーなど)には適用しない方が良いケースもある
  • スライサー同士でのフィルタリングが効かなくなるため、存在しない組み合わせでフィルターを設定してしまう可能性が高まる

最初の 2 つについては説明がなくても理解できると思いますが、最後の 1 つは以下のような意味です。例えば、「地域」で「関東」を選んでも、本来のスライサーとは異なり、「クエリの削減」によってすべての都道府県が表示されてしまいます。

その結果、気づかずに適当に選択すると、空白の結果が返ってくる可能性があります。これは通常のスライサーを使用した場合との大きな違いであるため、注意が必要です。

3. ドリルスルーの活用によるパフォーマンス制御

ここまで、レポートのパフォーマンスを向上させるためのさまざまなコツを紹介してきました。最後に、「ドリルスルーを活用して詳細表示を後段に回す」方法をご紹介します。

パフォーマンスを悪化させる典型的なパターンのひとつが、「最初から細粒度データを表示する」設計です。前回の記事とは逆の推奨となりますが、実際には最初から最も細かい粒度で表示しないことが望ましいやり方です。

前回からの繰り返しになりますが、200 万行の明細を持つテーブルビジュアルをページに直接置いた場合、ページ読み込み時に巨大なクエリが発行されます。そこでドリルスルー機能を使えば、最初は集計レベルのビュー(例:地域別・カテゴリ別)を表示し、ユーザーが特定の行を選択した場合のみ、その条件に応じた詳細ページを読み込むことができます。

一方、ドリルスルーという名称はExcelでも聞かれますが、Power BI のそれの定義と挙動が少し異なります。

Power BI のドリルスルー

定義
Power BI のドリルスルーは、レポート内で特定のデータ要素(行やカテゴリなど)を右クリックし、その要素をフィルター条件として別の詳細ページを開く機能です。

  • 主にレポートページ間の移動に使われ、遷移先のページには「ドリルスルーフィルター」が事前に設定されています
  • 例:地域別売上ページで「東京」を右クリック → 東京の詳細レポートページへ遷移

特徴

  • 遷移後のページは選択した要素で自動的にフィルタリングされる
  • レポート作成時に ドリルスルー専用ページ を作成しておく必要がある
  • 1ページ内でのデータ展開ではなく、ページ遷移 が伴う

下記レポートの「在庫分析」ページを例にすると、この機能は次のように動作します。
「企業〇」を選択すると、その企業〇に関する詳細分析ページへ移動できる、いわば対象を指定して詳細ページへ“飛ぶ” 機能となります。

🔱 https://aka.ms/pbireport

Excel のドリルスルー

定義
Excel のドリルスルーは、PivotTable(ピボットテーブル)、Power BIにおける「Excelで分析」、更に Power Pivot モデルで集計値をダブルクリックし、その集計値を構成する明細行(元データ)を新しいシートに展開する機能です。

  • 主に集計値の内訳を明細レベルで確認するために使われます
  • 例:売上合計セルをダブルクリック → 元データから該当レコードだけを抽出して新しいシートに表示

特徴

  • 新しいシートに明細データを展開する(元データ参照)
  • ページ遷移はなく、あくまで同一ブック内で明細を抽出
  • 集計元のデータモデルやソースが保持する行レベルデータに依存

ドリルスルーの実装

ここでは Power BI のドリルスルーについて、実装方法を整理しておきます。設定方法は公式ドキュメントでも確認できますが、本記事ではより分かりやすく、対象項目が選択されると「アイコンがハイライトされるタイプのドリルスルー」を例に解説していきます。

実装例

前回の例では Fact テーブル内の列をすべて使用した場合にパフォーマンスが良好でしたが、今回の実装例ではスタースキーマをベースに解説していきます。なお、このページは全てのフィルターを使用して即座にデータを反映させたいため、「クエリの削減」設定は行いません

ドリルスルー先ページの作成手順

① 新しいページ「Drill-through」を作成(※Power BI Desktopでは重複する名前のページを作成できてしまうため、注意が必要)
② 表示させた詳細情報を当該ページに作る
③ [書式]を選択
④ [ページ情報] → [ページの種類] → [ドリルスルー] を選択
⑤ ⏪[戻る] ボタンが自動挿入されていることを確認
⑥ 地域 (Region) と都道府県 (Prefecture) を選択。この2つが別のページで選択された場合、ドリルスルーが可能となる

DumpFilterの作成

ドリルスルー先のページは詳細表示に便利ですが、どの切り口でフィルターされたのか が分かりにくい場合があります。そこで役立つのが、「当該ページで適用中のフィルター項目を一覧表示する DAX メジャー」 を作成し、カード ビジュアルに表示しておく方法です。

DumpFilters は聞き慣れない名称かもしれませんが、考え方はシンプルで、現在ページのフィルター状況を可視化するものです。以下、その作り方を紹介します。

① Power BI DesktopからDAX Studioを立ち上げる

DAX Studioの左にあるテーブルを右クリック → Define Filters Dump Measure (All tables) を選択
③ クエリエディタ内のDAXクエリを全てコピー

④ Power BI Desktopに戻り、DAX Query Viewをクリック 
DAXクエリをペースト
⑥ [変更を含むモデルの更新] をクリック

⑦ 新しいカードビジュアルを作る
⑧ カードビジュアルを選択し、[DumpFilters]メジャーを[データ]にDrag & Drop
⑨ 名前を「フィルター状況」に変更
⑩ まだ何もフィルターされていないため、[--] になっていることを確認

DumpFilterの解説

DumpFilters メジャーのロジックは、簡単に言うと「指定した複数の列について、現在適用されているフィルター内容を文字列としてまとめて表示する」ものです。以下、各重要項目に関する解説となります。

処理の流れ(簡潔説明)

  1. 最大表示件数を設定
    • MaxFilters = 3 で、各列について最大3件までフィルター値を表示
    • それ以上ある場合は "..., [n items selected]" で省略表示
  2. 列ごとのフィルター判定
    • ISFILTERED(Column) で、その列にフィルターがかかっているか確認
    • フィルターがない列はスキップ
  3. フィルター内容の抽出と整形
    • FILTERS(Column) でその列のフィルター値を取得
    • COUNTROWS() で選択数をカウント
    • TOPN(MaxFilters, …) で表示件数を制限
    • CONCATENATEX() で値をカンマ区切りに連結
    • 件数が制限を超える場合は末尾に省略記号と件数を追加
  4. 列名と値を結合して出力
    • "ColumnName = 値1, 値2, 値3, ..." の形式に整形
    • UNICHAR(13) & UNICHAR(10) で改行し、次の列の出力に備える
  5. 全列を連結
    • この処理をリストアップされたすべての列に対して繰り返し、結果を文字列として連結
    • これをカードビジュアルなどに置くと、そのページで適用されている全フィルター内容が一覧表示される

最初の MaxFilters = 3 はどのように表示されるかというと、以下のようになります。

この35に変更すると、以下のように表示されるようになります。

DumpFilter は、現時点のセマンティックモデル内の列を DAX Studio から抽出して作成したものです。そのため、今後テーブルや列が追加された場合は、同じ手順で DumpFilter を再作成する必要があります。

参考: DumpFilters measure
https://www.sqlbi.com/articles/displaying-filter-context-in-power-bi-tooltips/

ドリルスルー元ページの作成

ここからは、ドリルスルーの元となるページ(本例ですが、「High-level」という名称)を作成していきます。ドリルスルー元のレポートには、次のようなメリットがあります。

  • ページ読み込み時の初期クエリ負荷を劇的に削減
  • 必要な時だけ詳細データを取得するため、全体の CU(Capacity Unit)消費が減る
  • ユーザーにとっても情報の階層構造が明確になり、ナビゲーション性が向上

ここで重要なポイントは以下の通り。

  • 本当に必要な指標・切り口だけを残す
  • 複数ビジュアルを統合
    • 小さなカードビジュアルを複数置く代わりに、マトリックスやテーブルにまとめる
  • 細粒度データの直接表示を避ける
    • 前述の通り、集計ビュー → 詳細ビューの流れにする

従って、ここからはデザインの世界になりますが、今回のニーズは地域別・都道府県別に担当者が分析を行う必要があるため、このニーズを満たすよう、「High-level」ページをデザインしていきます。

決して美しくはないですが、例えば以下のように「High-level」をデザインしてみます。

  • a: レポートタイトル
  • b: フィールド パラメーター(地域 / 都道府県の切り替え)=FP
    ※ FPの過去記事
  • c: ツリーマップビジュアル 
  • d: 地域スライサー
  • e: bのFPにより、地域・都道府県を自由に切り替えられるテーブル
フィールド パラメーターの作成

以下の順番でフィールド パラメーターを作成していきます。

  • Power BI Desktop → [モデリング] → [新しいパラメーター] → [フィード]
  • フィールド パラメーターを以下①~④の順番で作っていきます
  • フィールド パラメーターを確認し、「ボタンスライサー」を追加。なお、ボタンスライサーの設定はやや時間が掛かるので、慣れるまで触ってみることをお勧めします
  • ツリーマップにフィールド パラメーターを適用する
  • テーブルビジュアルを作る

これでフィールド パラメーターを活用した分析軸の切り替えが容易にできるようになりました。ここからは、いよいよ最後の機能である「アイコンがハイライトされるタイプのドリルスルー」の作り方をご紹介します。

ハイライトアイコンの作成方法

ドリルスルー用のアイコンを作成すると、次のような効果が得られます。

作成ステップ

1.「ボタン」から「空白」を追加し、[アクション] → 型 [ドリルスルー用] → 接続先 [Drill-through]

なお、この時点で「地域」または「都道府県」を選択し、「空白」を Ctrl + クリック することでドリルスルー先のレポートへ移動できますが、ここではその説明は割愛します。

2. DAXメジャーを作る

DAXメジャー:  条件分岐ドリルスルー

title_conditional_drillthrough = 
    -- ユーザーが現在選択している「地域」(Region) を取得
    -- SELECTEDVALUE は単一値が選択されている場合にその値を返し、複数または未選択の場合は BLANK() を返す
    VAR RegionSel = SELECTEDVALUE(dPrefecture[Region]) 

    -- ユーザーが現在選択している「都道府県名」(PrefectureName) を取得
    VAR PrefSel = SELECTEDVALUE(dPrefecture[PrefectureName]) 

    -- 表示ラベルを決定
    -- 都道府県が選択されていれば PrefSel を使用、そうでなければ地域(Region) を使用
    VAR Label = COALESCE(
        PrefSel,   -- 第一優先: 都道府県名
        RegionSel  -- 第二優先: 地域名
    ) -- PrefectureがなければRegionを使う

    RETURN
        -- ラベルがBLANK()の場合(何も選択されていない場合)は「⚫ ドリルスルー」を表示
        -- そうでなければ、「🟢 {選択値} へ」という形で表示
        IF(
            ISBLANK(Label),
            "⚫ ドリルスルー",
            "🟢 " & Label & "へ"
        )

こちらの DAX メジャーをコピーし、Power BI Desktop で新規メジャーを作成して貼り付けます。なお、こちらはフィールド パラメーター用の条件分岐メジャーです。もし1つの軸だけで良い場合(例:都道府県)は、DAX コードを以下のように簡略化できます。

DAXメジャー:  都道府県ドリルスルー

 title_prefecture_drillthrough = 
        IF(
            SELECTEDVALUE(
                dPrefecture[PrefectureName],
                0
            ) == 0,
            "⚫ ドリルスルー",
            "🟢 " & SELECTEDVALUE(Data[PrefectureName]) & " へ"
        )

ここで重要なのは、これらの DAX メジャーはあくまで表示用であり、ドリルスルー機能そのものを実現するものではないという点です。上述の通り、表示にこだわらないのであれば、作成ステップ 1 の時点でドリルスルーはすでに実現されています。

3. ボタンアイコンのテキストに「条件分岐ドリルスルー」を適用

以下のように、ボタンをアクティブにし、「ボタンのスタイル」から③~⑥まで実行します。

DAXメジャー名の一部を入力し、対象メジャーを選択します。

[書式] → [相互作用を編集] → テーブルを選択 → ボタンの相互作用を🚫から別のアイコン💹に変更します。

4. 最後の”お化粧”

この状態でも良いという人もいると思いますが、せっかくなのでもう少し”お化粧”をしていきます。

  • 「ボタンのスタイル」が [既定] になっていることを確認
  • 「フィル」を有効にし、[カラー] をライトイエローに変更。罫線を3pxから1pxへ変更
  • 「ボタンのスタイル」を「ポイントしたとき」に変更
  •  テーブルをクリックした状態にすると、結果が反映されていることを確認できる。「ポイントしたとき」をライトグリーンに変更し、カーソルを持っていくと、設定したカラーが反映される

5. 動作確認

最後に、ここまでの流れをまとめた動画をご用意しましたので、効果をご確認いただけます。
www.youtube.com

おまけ: ページで使用するビジュアル数を制限

1ページあたりのビジュアル数を必要最小限に抑えることは、レポートのパフォーマンス改善に非常に効果的です。理由はシンプルで、各ビジュアルが独立してクエリを発行するためです。

例えば、10 個のビジュアルがあれば、裏側では 10 個のクエリが並列または順次実行されます。さらに、それぞれが大きなテーブルや複雑な DAX を参照していれば、待機時間はページ全体の体感速度に直結します。

これは「ドリルスルーを活用したパフォーマンス制御」と考え方が近く、1ページに配置するビジュアル数を制限することで、全体的なパフォーマンス向上が期待できます。特に DirectQuery は Import モデルよりクエリ性能が劣るため、同時接続ユーザーが増えると多数のビジュアルから発行されるクエリが負荷となり、さらにパフォーマンスが低下します。

Import モデルは最速ですが、それでも不要なビジュアルは極力減らし、「質問に答えられるレポート作り」を意識すべきです。レポート作成のベストプラクティスについては、以下の Docswell や本ブログの基礎解説記事をご参照ください。
www.docswell.com

分析用レポートの基礎

marshal115.hatenablog.com

marshal115.hatenablog.com

marshal115.hatenablog.com

まとめ

今回紹介した手法は、モデル変更なしでもパフォーマンス改善が可能なアプローチです。

手法 主な効果 注意点
クエリ削減設定 不要な再計算を防ぎ、複数スライサー操作時の体感速度向上 適用ボタンの押し忘れ対策
ドリルスルー 初期ロード負荷削減、ナビゲーション性向上 ページ遷移設計が必須
ビジュアル削減 ページ全体のクエリ発行数削減 情報不足感を補う工夫

パフォーマンス改善は「高速化」だけが目的ではありません。容量の健全性維持、運用コスト削減、ユーザー体験の向上 に直結します。
モデル設計・DAX 最適化と合わせて、レポート設計の段階でもこれらのテクニックを取り入れることで、より軽快でストレスのない Power BI 環境を実現できます。