LoginSignup
5
6

Power Query workout - クエリの評価は一度だけとは限らない

Last updated at Posted at 2023-09-19

クエリを分割するアプローチ採用したとき、はて?と思うことがあるようだ。なぜ何回もクエリを評価してしまうの?と。

Power Query エディタだけを眺めていると評価済みの結果が再利用されるのでは?そう錯覚したり期待するかもしれない。プレビュー用途や処理の都合上キャッシュが用意されることはあるけれど、別のクエリで再利用するという動作はしない。そもそも Power Query だけでクエリの評価結果を保存することはない。

たとえば

クエリの評価が一度だけとは限らない、つまり、クエリは必要なだけ繰り返し評価されるのはなぜ?という動作にはいくつかある。シンプルなケースで、
クエリ: SourceQuery を参照するクエリ、QueryA と QueryB があり、
image.png
QueryA が評価されるとき、SourceQueryは評価される。
image.png
QueryB が評価されるとき、SourceQueryは評価される。
image.png
ここでは SourceQuery は少なくとも2回評価されるということだ。一連のクエリの評価で Refresh All としても、QuaryA と QuaryB が個別に評価されるだけ。再利用するためにそれぞれ結果を保存するわけがない。
評価されたクエリの結果を使いまわせれば効率的なのでは?と思うかもだけど、SourceQuery の結果が 数 TB あったらどうするの。メモリがどれだけ必要なの?って話。扱えるデータ量にしきい値があるのは道具の用途としてよくない話だと思うね。

動作の実証

コードで実証するのは簡単

評価ごとに評価される動作

Power Query
// SourceQuery
#table(
    type table [Column1 = nullable text],
    {
        {
            Text.NewGuid()
        }
    }
)

// Query1
SourceQuery

// Query2
SourceQuery

たとえば、Excel で [Reflesh All] してもそれぞれ異なる結果になる。
image.png
SourceQuery / Query1 で SourceQuery を参照 / Query2 で SourceQuery を参照 ですべてテーブルとしてロードしているから、少なくとも 3回

Table.Buffer 関数を使っても動作は変わらない。Table.Buffer を勘違いしているひと多いよね。

Power Query
// SourceQuery
Table.Buffer(
    #table(
        type table [Column1 = nullable text],
        {
            {
                Text.NewGuid()
            }
        }
    )
)

バッファリングにより評価済みの値はメモリにキャッシュされるけれども、キャッシュが共有されるわけではない。

最初に理解すべきこと

見た目でそう思い込むことは不思議ではない。けど、クエリの評価結果を参照しているクエリに渡すという動作をしているわけではないということがポイント。

Power Query
// SourceQuery
    Text.NewGuid()

// Query1
    SourceQuery

Query1 が評価されるとき、SourceQuery の評価結果、つまり "Text.NewGuid() の結果" を取得するのではなく式 "Text.NewGuid()" を参照しているということ。

思ったこと🙄

クエリの分割が可能というのは、論理的アプローチで実現している。

その他

5
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
6