はじめに
PBIJP Semantic Data Modeling workout #8 で発表した内容を纏めました。
Power BIデスクトップにTMDLビューが搭載されるとの発表がありました。
今までTabular EditorやAPIなどでしか変更出来なかったセマンティックモデルのプロパティがPower BIデスクトップからも変更できるようになります。
その記事の中で 「IsAvailableInMDX」 の例が載っていました。今までBest Practice Analyzerで度々みていたので存在は知っていたものの、深く理解していなかったのでこれを機に試してみました。
IsAvailableInMDXとは?
その前に MDX (Multi Dimensional eXpressions)ですが、多次元データベース(キューブ)に対するクエリ言語です。Microsoft以外でも広く使用されている業界標準といってもよい言語だと思います。昔々、DAX登場以前に習得してみようかと思ったもののすぐに挫折をした記憶があります…。
それはともかく、Power BIの世界では 「Excelで分析」 機能がありますが、ここではExcelのPivotテーブルとセマンティックモデルとの対話は MDX を介して行われています。
MDXで会話を行う為に、Power BIセマンティックモデルでは 属性階層 を作成しています。インポートモデルではその分、処理時間とモデルサイズに影響を与えるので、ExcelのPivotテーブルで行・列に使用しない列には「IsAvailableInMDX」をfalseにすることで属性階層が作成されなくなり、 処理時間の短縮 及び モデルの軽量化 ができるということになるはずです。
Direct Lake モードのセマンティックモデルでも、「IsAvailableInMDX」のプロパティは存在しており、 「Excelで分析」機能が使用できる ものの、モデル上に属性階層での容量を確認することはできませんでした。
どの列の「IsAvailableInMDX」をfalseにすべきか
Power BIのモデリングでは スタースキーマ モデリングがベストプラクティスとされており、明示的なメジャーを作成し、スライスはディメンションテーブルを使用し、使用しない列は非表示にするのがよいとされていますが、これをちゃんとやるとファクトテーブルにはメジャーしか残らなくなります。当然、Excelでもディメンションテーブル列とメジャーだけあればよいので、 ファクトテーブルのすべての列を「IsAvailableInMDX」をfalseにするのがよい と思いました。
試してみた
単純化するためにContosoモデルから3つのテーブルのみでインポートモードのセマンティックモデルを作成しました。Salesテーブルはすべて非表示にしています。
本当にExcel PivotテーブルがMDXを使用している?
DAX StudioのALL Queriesを使いExcelで分析のクエリをトレースしてみました。MDXが発行されていますね。
SELECT
FROM
[Model]
WHERE
([Measures].[Sales Amount]) CELL PROPERTIES VALUE,
FORMAT_STRING,
LANGUAGE,
BACK_COLOR,
FORE_COLOR,
FONT_FLAGS
TMDLビューで属性を変更する
TMDLビューからSalesテーブルをドラッグするとスクリプトが挿入されます。
ですが、「IsAvailableInMDX」が表示されません💦
念のためTabular Editorでデフォルト値を確認します。trueですね。
TMDLビューに戻り属性名を打ち始めるとインテリセンスが効いてサジェストされました。
モデルサイズと処理時間の比較
DAXスタジオでプロパティ変更前後の統計を比較しました。
デフォルト(「IsAvailableInMDX」が true )
Salesテーブルのすべての列の「IsAvailableInMDX」を false に変更
処理時間は12分から11分とわずかに短縮されました。
また、属性階層のサイズがゼロになり、Salesテーブルのサイズが縮小されたのが確認できました。
副作用
SQL BIの記事に以下がありました。
属性階層には列の統計情報が格納されており、フィルターコンテキストが存在しない場合に、列をスキャンすることなく値をとることができます。
「IsAvailableInMDX」をfalseにすることの副作用として、フィルターコンテキストがない列の情報もScanして取得するようになります。
以下のDAXクエリーを試してみます。
EVALUATE
{
DISTINCTCOUNT(Customer[City])
が
「IsAvailableInMDX」が true の場合はScanが発生せずに結果を取得できます。
「IsAvailableInMDX」を false に変えると…、Scanが発生しました。
また、 Direct Lakeモード では、「IsAvailableInMDX」が true でもScanが発生しました。
おわりに
副作用については、実際の現場ではフィルターコンテキストがない状態というのは考えにくいので、あまり気にしなくてもいいように思いました。フィルターコンテキストがない状態では列の統計情報から結果を得ることができるのは知っていましたが、それが「IsAvailableInMDX」に依存してるのは新しいmでした。
一方で、Direct Lakeモデルは属性階層が無いようにみえるけどMDXは使えるという謎が残りました…。