Microsoft Fabricの登場により、データ分析の風景が大きく変わりました。2025年7月現在、FabricはPower BIを含む統合プラットフォームとして、新規ユーザーを急速に引きつけています。しかし、Power BIの基礎知識がないまま自己流でモデリングを進めるユーザーが増え、非効率なモデルが生まれています。たとえば、過剰に複雑なテーブル構造や冗長なデータが混在し、レポートのパフォーマンスが落ちるケースが目立ちます。
このままでは、FabricやPower BIへの信頼が揺らぎ、利用が敬遠されるリスクがあります。こうした問題を防ぐ鍵は、「スリムなデータモデル」の構築です。スリムなモデルはデータサイズを抑え、パフォーマンスを高め、メンテナンスを容易にします。これはFabricユーザーだけでなく、従来のPower BIユーザーにとっても最重要課題です。
なぜスリムなモデルが重要か?それは、データ分析の目的である「迅速なインサイト提供」を実現するためです。巨大で扱いにくいモデルは処理速度を遅らせ、ユーザー体験を阻害します。一方、小さく洗練されたモデルは効率的な処理と柔軟な拡張性を両立させます。このブログでは、スリムなモデルの利点を、モデリングのベストプラクティス、データサイズの観点、キャッシュの活用、Direct Lakeの改善策を通じて詳しく解説します。中級者から上級者向けに、実践的な知見を提供します。
📖 目次
Power BIでレポートパフォーマンスを最適化するには、「スタースキーマ」が最良の選択です。スタースキーマは、中央にファクトテーブル(例:売上データ)を置き、ディメンションテーブル(例:顧客、商品、日付)で囲む構造です。 この設計の利点は、データ量の削減とクエリ効率の向上にあります。たとえば、フラットな(大福帳)単一テーブルでデータを保持すると、顧客名や商品名が何度も重複し、データサイズが膨張します。しかし、スタースキーマではこれらをディメンションテーブルに分離し、ファクトテーブルにはキー値だけを保持します。これによりデータ量が減り、Vertipaqエンジン*1の圧縮効率が向上します。 具体例を見てみましょう。小売業者が売上データを管理する場合、フラットテーブルでは「注文日」「顧客名」「商品名」「数量」「単価」が1行ごとに繰り返されます。100万行のデータがあれば、同じ顧客名が何千回も出現し、冗長性が増します。一方、スタースキーマでは「顧客」テーブルに顧客IDと名前を、「商品」テーブルに商品IDと名前を分離し、ファクトテーブルにはIDと数量・単価のみを記録します。これでデータサイズが半分以下になることもあります。 さらに、スタースキーマはDAXメジャーのシンプル化にも寄与します。適切なモデルなら、複雑なフィルターやイテレーションを避け、単純な計算で済みます。たとえば、「総売上」を計算する際、フラットテーブルでは条件を多用したDAXが必要ですが、スタースキーマではシンプルな記述で対応可能です。これがレポート作成の基盤を強固にする理由です。 モデリングのベストプラクティスについては、次のリソースが参考になります: データモデルのサイズはPower BIのパフォーマンスに直結します。ここでは、モデルサイズを3つの状態で分解し、それぞれの特徴と影響を詳細に解説します。また、サイズ肥大化の原因と対策も掘り下げます。 pbixで保存した状態 DAX StudioのVertipaq Analyzerで確認した状態 クエリを開始した状態 モデルサイズの肥大化やCPU急上昇の原因は以下に集約されます: 上記DAXメジャーは「カテゴリー」が雑貨、かつ、「年数値」が2021の商品CDをカウントした指標ですが、どちらの場合でも、FILTER関数を使ってSalesテーブル全体をスキャンしていることから、不要な行まで処理され、メモリとCPUを浪費します。1,600万行のデータで処理した結果は以下の通り。
解決策として、必要な列だけをフィルターするアプローチが有効です。たとえば、ディメンションテーブル「dProduct」と「dCalendar」を使い、以下のように列だけを参照した形に書き換えます。 これで、スキャン対象が絞られ、処理が効率化されます。処理パフォーマンスは以下の通りですが、クエリプランが最適化されたことに加え、パフォーマンスも7倍速くなっています。
モデリングの設計ミス:スタースキーマを無視し、フラットテーブルや不要な列を含めると圧縮効率が落ちます。「注文コメント」列のような高カーディナリティデータが残るとサイズが増大します。 不要な行・列の混入:分析に不要な過去データや中間計算用の列が残るとリソースを浪費します。たとえば、10年前の売上データを保持する必要がない場合、削除すべきです。 Direct Lakeモードでもスリムなモデリングが重要です。Delta Parquet形式のデータ*6をOneLakeから直接読み込みますが、不要な列を含めると効率が落ちます。メダリオンアーキテクチャ*7のSilver層テーブルをそのまま使うのは避けるべきです。Silver層は広範なデータを保持しますが、200列のテーブルではV-orderの効果が低下し、メモリ効率が落ちます。20列に絞ったテーブルなら、Vertipaqエンジンにとってフレンドリーで、パフォーマンスが向上します。 キャッシュは、Power BIのパフォーマンスを支える重要な仕組みです。ここでは、データキャッシュとレポートキャッシュの違い、活用ケース、モードごとの戦略を詳細に解説します。 データキャッシュとレポートキャッシュの違い キャッシュを利用すべきケース Power BIを効果的に活用するには、「スリムなモデル」を追求することが不可欠です。スタースキーマを採用し、不要なデータを取り除くことで、パフォーマンスが向上し、リソース消費が抑えられます。モデルサイズの管理、効率的なDAX記述、キャッシュの活用、Direct Lakeの最適化は、いずれもこの目標を支えます。しかし、これらのスキルは一朝一夕には身につきません。モデリングやDAXの知識は、継続的な学習と実践で磨かれます。短期的な成果を求めるのではなく、長期的な視点でスキルを育ててください。 *1:Power BI, Excel Power Pivot, SQL Server Analysis Services(SSAS)Tabular モデルのインメモリデータ処理エンジン。VertiPaq は、「Verti=列指向、Paq=圧縮 (パッキング) 」を組み合わせたものであり、大量データを効率よく圧縮・検索・集計するために設計されています *2:VertiPaq は、カーディナリティ(ユニーク値の数)が限られた列に対して「辞書」を作成します。具体的にはa) 各ユニークな値に対して 数値キー(インデックス) を割り当て、b) 元の値を保持せず、キーで内部的に参照、といった処理を行います *3:数値データを効率的に格納 *4:ソースがCSV、1,300万行 × 22列、最大ユニーク行数160万で1.3GBのサイズ *5:「インスタンス」は実行環境(サービス単位)であり、 Power BI の Import モデルや セマンティックモデルは Analysis Services(Tabular モード)をベースに動作しています *6:Parquet をベースにした トランザクション管理付きの拡張フォーマット。データの 追記・更新・削除(ACIDトランザクション)を可能にします *7:データの品質と整備レベルに応じて段階的に整理・処理するデータ構造の設計手法です。特に Databricks や Microsoft Fabric などのモダンなデータプラットフォームで使われます。Medallionアーキテクチャは、「生データ(Bronze)→整形データ(Silver)→ビジネス活用データ(Gold)」という段階的処理により、信頼性の高い分析基盤を構築するベストプラクティスとなりますモデリングのベストプラクティス
- Power BIのベストプラクティス①
- Power BIのベストプラクティス②
これらではテーブル関係やデータ型の最適化が詳述されていますが、ここではスリムなモデルの構築プロセスをさらに深掘りします。不要な列の削除や高カーディナリティデータの排除が重要です。「コメント」や「メモ」といったテキスト列は、分析に寄与しない場合、モデルから除外すべきです。また、日付テーブル(①、②、③)の基礎に従い、スタースキーマにすることが肝要です。これにより、モデルが軽量になり、長期的な運用が容易になります。データモデルのサイズ
この状態は、Vertipaqエンジンによりデータが最大限に圧縮された形です。列指向のストレージを使用し、各列のユニーク値をDictionary(辞書)*2に変換してエンコード*3します。たとえば、数値データはビット単位で圧縮され、文字列も重複が排除されます。1,000万行の売上データが50MB程度*4に収まるケースもあります。この圧縮状態はファイルの保存や共有に最適で、クラウドへのアップロード時間も短縮されます。ただし、圧縮率はデータの特性に依存します。低カーディナリティの列(例:性別)は高く圧縮されますが、ユニーク値が多い列(例:注文ID)は効率が落ちます。
Analysis Services (AS) インスタンス*5にデータがロードされた状態です。pbixから展開されたデータがメモリに保持されますが、一部は非圧縮のままです。たとえば、Dictionaryは圧縮されず、ユニーク値のリストとしてメモリを占有します。1列に100万のユニーク値があれば、数MB単位でサイズが増えます。また、キャッシュ(クエリ結果の一時保存)やメタデータ(テーブル構造情報)も加わり、pbixよりサイズが膨張します。Vertipaq Analyzer(下記「DAX Studioの紹介」を参照)で列ごとのサイズや圧縮率を確認すると、非効率な列(例:高カーディナリティの文字列)を特定できます。
www.docswell.com
クエリ実行時にはCPUとメモリ使用量が急上昇し、②の状態より大幅に膨張します。理由は、クエリ処理に必要な一時テーブルがメモリ内に生成されるためです。たとえば、非圧縮の行データが大量にあれば、行数×数KBの単位でメモリが肥大化します。ピーク時には10GBを超えることもあります。さらに、フィルターや集計処理でCPU負荷が増し、並列処理が発生するとリソース消費が顕著になります。
//前提として、Sales (ファクト) にCategoryとYearが存在しており、フラットテーブルの状態でSalesテーブル全体をフィルター
商品数カウント_非効率1 =
CALCULATE (
DISTINCTCOUNT( Sales[ProductKey] ),
FILTER (
Sales,
Sales[Category] = "雑貨" &&
Sales[Year] = 2021
)
)
//前提として、スタースキーマであるが、Salesテーブル全体をフィルター
商品数カウント_非効率2 =
CALCULATE (
DISTINCTCOUNT( Sales[ProductKey] ),
FILTER (
Sales,
RELATED( dProduct[Category] ) = "雑貨" &&
RELATED( dCalendar[YearNumber] ) = 2021
)
)
SE Queriesが9となっており、複数のスキャンが実行されていることから、CPUの消費が激しいことを確認できます。
商品数カウント_効率 =
CALCULATE (
DISTINCTCOUNT( Sales[ProductKey] ),
dProduct[Category] = "雑貨",
dCalendar[YearNumber]= 2021
)
キャッシュについて
データキャッシュは、クエリ結果や中間計算をメモリに保存する仕組みです。同一クエリが再実行されると、ディスクや外部ソースにアクセスせず、キャッシュからデータを取得します。これにより、応答時間が短縮されます。一方、レポートキャッシュは、レポートページ全体のレンダリング結果を保存します。ユーザーがページを再訪した際、ビジュアルの再描画が不要になり、表示が瞬時に完了します。データキャッシュはバックエンド処理の効率化、レポートキャッシュはフロントエンドのユーザー体験向上に寄与します。たとえば、売上合計を計算するクエリはデータキャッシュで高速化され、ダッシュボードのグラフ表示はレポートキャッシュで迅速化されます。
キャッシュは、以下のシナリオで特に有効です。
インポートモードでは、データがメモリに常駐するため、データキャッシュが自動的に機能します。たとえば、同一フィルターでの集計クエリが繰り返されると、キャッシュから即座に結果を返します。ただし、モデルサイズが大きいとメモリが圧迫され、キャッシュの効果が薄れる場合があります。対策として、不要な列を削除し、モデルを軽量化することが重要です。一方、Direct Lakeモードでは、データがOneLakeからオンデマンドで読み込まれます。初回クエリは遅延が発生しますが、頻用クエリをキャッシュに保持することで、2回目以降の応答性が向上します。例えば、ユーザーAが売上上位10商品のクエリを発行した場合、それがキャッシュされるようになるため、ユーザーBが同じクエリを発行すると、待ち時間が短縮されてビジュアルが表示されるようになります。最後に
行き詰まった場合、ネット上のリソースが助けになります。前述のブログ、Microsoft公式ドキュメント、Power BI Communityを活用してください。Small is beautiful—小さなモデルが大きな価値を生み出します。この原則を胸に、Power BIやFabricでのデータ分析を深化させてください。