QueryRowsのレコード件数カウントについて

古いバージョンの知識のまま覚えていたので、新しく自分の頭をアップデート。
リリースノートはこまめにチェックしないと。
なかなか分厚くて、リリース試験ででるものしか確認することはないんだけどね。

スポンサーリンク

クエリ行のカウントの方法が変わりました

Summer18からクエリ行のカウント方法が変わりました。

以前は

集合関数を使用した時、対象のレコード数がそのままクエリ行としてカウントされるようになりました。
例えば、取引先が10件ある状態で、COUNT関数などの集合関数を実行した時、カウント対象のレコード10件がカウントされます。

よく検索処理でありがちな、件数をカウントしてからリストに出すという処理をした場合、件数カウントで10件、実際の検索で10件とクエリ行が2倍消費されるため、事前の件数確認がガバナに大きく影響するため不向きだったのです。

これからは

集合関数を使用した時、返却されるレコード数がそのままクエリ行としてカウントされるようになりました。
つまり、取引先が10件の状態で、集合関数を実行した場合、カウント用に返却されたレコード1件のみがクエリ行としてカウントされるようになりました。

これはかなり使い易くなりました!
ユーザからのアイデアを受けて改善されたそうです。
アイデアを出した人、サンクス!

一応確認してみる

まずは、以下のリードのレコードを準備。

名前 会社名
hoge1-1 hoge1
hoge1-2 hoge1
hoge2-1 hoge2
hoge3-1 hoge3
hoge3-2 hoge3
hoge3-3 hoge3

以下のソースコードでクエリ行をカウント

System.debug('before:' + Limits.getQueryRows());
Integer x = [Select Count() From Lead];
System.debug('after:' + Limits.getQueryRows());
System.debug('max:' + Limits.getLimitQueryRows());

カウントされた結果

before:0
after:1
max:50000

うん、カウントは1レコード分になってますね。

今後はGroup byを使って、複数カウントされるケースを作りました。
以下のソースで会社名ごとにカウントします。

System.debug('before:' + Limits.getQueryRows());
List<sObject> x = [Select Company, Count(Id) From Lead Group by Company];
System.debug('after:' + Limits.getQueryRows());
System.debug('max:' + Limits.getLimitQueryRows());

ちなみに、SOQL実行で返却されるレコードはこちら。

Companu Count(Id)
hoge1 2
hoge2 1
hoge3 3

マニュアル通りであれば、3件分カウントされるはずですが。

before:0
after:3
max:50000

バッチし!思った通りに、グループ化された単位でカウントされていました。

集合関数ではないけど

次はリレーションを使って、親と子のレコードを取得した時のクエリ行はどうなるか?
こちらの取引先&取引先責任者(4件)を使ってクエリ行数のカウントを確認しました。

Name Contacts
United Oil & Gas Corp. [{“LastName”:”Pavlova”},{“LastName”:”Boyle”},{“LastName”:”Song”},{“LastName”:”Green”}]
System.debug('before:' + Limits.getQueryRows());
List<Account> a = [Select Name, (Select LastName From Contacts) From Account where Name = 'United Oil & Gas Corp.'];
System.debug('after:' + Limits.getQueryRows());
System.debug('max:' + Limits.getLimitQueryRows());

こちらは結果はこう

before:0
after:5
max:50000

つまり、クエリ行数が5件なので、取引先1件+取引先責任者4件の合計がカウントされています。
子レコードを取得するときは、親レコードと子レコードの合計がクエリ行数になるので、こちらは制限オーバーしないように注意しましょう。

まとめ

  • 集計関数を使用したときのクエリ行数はカウント用レコード件数分消費される(対象のレコード件数でなくなった)
  • リレーションを使用して子レコードを取得するときは、親レコード+子レコードの件数がカウントされる

コメント