スケーラブルな計算を設計する
モデルは構造化されています。 次に、データとチームの成長に合わせてパフォーマンスと保守性を維持する計算を設計します。 小規模では、メジャーが重複し、名前に一貫性がないモデルは、理想的でない場合でも引き続き動作します。 大規模になると、故障します。 何百ものメジャーを持つモデルには、重複したロジックを防ぎ、大規模なデータセットに対するクエリ時間を短縮し、新しいチーム メンバーがエラーを発生させずにモデルを理解して拡張できるようにする構造設計上の決定が必要です。
このユニットでは、メジャーの過剰増加を抑える計算グループ、チームの保守性を向上させるためのDAXの読みやすさに関する規則、大規模なファクトテーブルにおけるクエリ性能向上のための集計、という3つのパターンについて説明します。
計算グループ
複数のメジャーに対して同一の計算パターンを適用するモデルオブジェクトが計算グループです。 バリエーションごとに個別のメジャーを作成する代わりに、パターンを 1 回定義し、動的に適用します。
計算グループが解決する問題
50 の基準メジャー (総売上、総コスト、利益、販売単位など) を持つ組織を検討します。 各指標には、年初来、四半期初来、月初来の計算が必要です。 計算グループがない場合は、50 × 3 = 150の余分なメジャーが必要になります。 前年との比較を加えると、維持すべきメトリクスが250以上になります。
計算グループでは、タイム インテリジェンス パターンごとに計算項目を含む 1 つのグループを作成します。 これらの項目は、モデル内の任意のメジャーに自動的に適用されます。
計算グループのしくみ
計算グループには計算項目が含まれています。それぞれ、 SELECTEDMEASURE()を使用して現在のメジャーを変更する DAX 式を定義します。 タイム インテリジェンス計算グループを次に示します。
// Year-to-Date
CALCULATE(
SELECTEDMEASURE(),
DATESYTD('Date'[Date])
)
// Quarter-to-Date
CALCULATE(
SELECTEDMEASURE(),
DATESQTD('Date'[Date])
)
// Month-to-Date
CALCULATE(
SELECTEDMEASURE(),
DATESMTD('Date'[Date])
)
ユーザーがビジュアルに計算グループを追加すると、各組み合わせに対して個別のメジャーを使用せずに、任意のメジャー (Total Sales、Profit、Units Sold など) の YTD、QTD、MTD を切り替えることができます。
動的書式指定文字列
動的書式指定文字列は、計算項目のコンテキストに基づいて表示形式を変更します。 たとえば、パーセント計算はパーセンテージで表示され、通貨計算は同じ基準メジャーに適用された場合でも通貨として表示されます。
// In the format string expression for a YoY % calculation item:
"0.0%"
動的書式指定文字列を使用すると、個別の書式設定メジャーの必要性が軽減され、モデル全体で書式設定の一貫性が保たれます。
ヒント
Power BI で計算グループを作成する方法について詳しく学びます。
計算グループを使用するタイミング
3つ以上の指標に同じ計算パターンを適用する必要がある場合は、計算グループを使用します。 一般的なユース ケースには、タイム インテリジェンス (YTD、QTD、MTD)、通貨換算、差異計算 (実績と予算) があります。
DAX の読みやすさの規範
200以上の指標を維持するチームにおいて、読みやすさは大規模な環境での設計上の決定であり、個人的な好みではありません。 一貫性のある読み取り可能な DAX を使用すると、メンテナンス エラーが軽減され、新しいチーム メンバーがモデルを理解しやすくなります。
変数
変数は中間結果を格納し、読みやすさを向上させ、エンジンが同じ式を複数回評価できないようにします。
Profit Margin =
VAR TotalRevenue = SUM(Sales[Revenue])
VAR TotalCost = SUM(Sales[Cost])
VAR ProfitAmount = TotalRevenue - TotalCost
RETURN
DIVIDE(ProfitAmount, TotalRevenue)
変数がない場合、同じ SUM(Sales[Revenue]) 式が複雑なメジャーに 3 回表示されることがあります。 変数は式を 1 回評価し、結果を再利用します。
ヒント
変数を使用して DAX 数式を改善する方法について詳しく説明します。
名前付け規則
モデルが複数の担当者によって維持される何百もの指標を持っている場合、一貫性のある命名が重要です。 次の規則を確立します 。
- メジャー名: "Total Sales" や "YoY Revenue Growth" などのわかりやすい名前を使用します。元の作成者だけが理解する省略形は避けてください。
-
変数名: 中間値を説明するわかりやすい名前を使用します (
TotalRevenueやxではなく、tempなど)。 - 計算グループ項目: アイテムの動作方法ではなく、その機能に基づいて名前を付けます (「DATESYTD ラッパー」ではなく、「Year-to-Date」など)。
記述的な名前付けは、AI の使用にも重要です。 Copilotまたはデータエージェントは、モデルにクエリをする際に、測定名と説明を使用して、どの計算を含めるかを判断します。 "YoY Revenue Growth" という名前の指標は "Calc7_v2" よりも優れた AI 結果を生み出します。
ヒント
Power BIのCopilotは、DAX 数式の記述と説明に役立ちます。 複雑な指標に取り組んでいる場合は、Copilotを使用して改善点を提案したり、既存のロジックを説明したりすることができます。
反復子と集計関数
反復子関数 (SUMX、 AVERAGEX、 MAXX) は、テーブルに対して行ごとの式を評価します。 集計関数 (SUM、 AVERAGE、 MAX) は、1 つの列で動作します。 大量のデータでは、次の選択肢が重要になります。
- 1 つの列を集計する場合は、集計関数を使用します。 エンジンは事前構築済みのデータ構造を使用できるため、高速です。
- 計算に行レベルの式 (行ごとの
Quantity × UnitPriceなど) が必要な場合は、反復子を使用します。
Note
反復子はすべての行を処理します。これは、大きなファクト テーブルのパフォーマンスに影響を与える可能性があります。
防御パターンの情報関数
ISBLANK、HASONEVALUE、ISINSCOPEなどの情報関数は、フィルター コンテキストが異なる複数のレポートで用いられるメジャーに対して、防御的なパターンを作成します。
Sales per Customer =
IF(
HASONEVALUE(Customer[CustomerID]),
DIVIDE(SUM(Sales[Amount]), 1),
DIVIDE(SUM(Sales[Amount]), DISTINCTCOUNT(Sales[CustomerID]))
)
これらのパターンは、元の作成者が予測していなかったコンテキストでメジャーが使用されている場合に予期しない結果を防ぎます。
Aggregations
集計とは、事前計算された合計を詳細データよりも高いグレインで格納する集計テーブルです。 クエリが最初にこれらのテーブルにヒットし、大規模なファクト テーブルのパフォーマンスが向上します。 クエリが集計と一致すると、エンジンは数百万行の詳細行をスキャンするのではなく、小さいサマリー テーブルから結果を返します。
設計上の決定としての集計
集計を追加するタイミングと粒度を決定することは、設計上の判断です。 パフォーマンスの監視とチューニングは個別の運用上の問題ですが、モデルの設計時に構造上の選択を行います。
次の場合は集計を検討してください。
- ファクト テーブルは数百万行を超え、一般的に使用されるクエリは、より高い粒度 (リージョン別の月次合計など) でデータを集計します。
- ユーザーは、概要レベルのビジュアルでクエリの応答時間が遅くなります。
- ほとんどのレポート操作では、行レベルの詳細は必要ありません。
ストレージ モードによる集計動作の違い
インポート モードでは、集計は個別の非表示テーブルとして格納されます。 エンジンは、一致するクエリを集計テーブルに自動的にルーティングします。
Direct Lake モードでは、デルタ テーブル自体を集計ソースとして使用できます。 Direct Lake は列形式の Parquet ファイルを読み取るため、エンジンは、多くのシナリオで集計なしで大規模なデータ ボリュームを処理できます。 クエリ パターンでニーズが確認された場合にのみ、集計を追加します。
ヒント
Power BI のユーザー定義集計の詳細については、