こんにちは、アンダーソンです。
今回は前回に引き続き実験シリーズです。
SOQLを動的にとりたいなんてことは当然のようにあるはないかと思いますが、
その際に、動的SOQLにするのがいいのか、バインド変数を使うのが良いのかなどやり方はいろいろあると思います。
ただ大きなプロジェクトになると立ちはだかるのがパフォーマンスの問題です。
今回はできるだけパフォーマンスがよくなる実装のまず一つとしてSOQLで実験してみたいと思います。
Contents
前提条件
前提条件として今回は1万件の取引先責任者をとってくるというSOQLを用意します。
ただ単純にとってくるだけでは意味がないので回りくどい取り方をしようかなと思ってます。
データとしては
- テスト1〜10000という名前の取引先
- 全ての取引先はGrand Hotels & Resorts Ltdという取引先
- Levelという項目には一律Primaryという値を入れる
という一律のデータを用意してどんな形でも1万件出てくるようにしてみました。
そして試したSOQLが下記です。
SELECT Id FROM Contact WHERE AccountId IN (SELECT Id FROM Account) AND Level__c = 'Primary' AND LastName LIKE 'test%'
これをすこしづつ変更してやっていきます。
まずはそのまま
先ほどのSOQLでそのまま実行してみます。
一応参考までに下記が実行した内容です。
List<Contact> conList = [SELECT Id FROM Contact WHERE AccountId IN (SELECT Id FROM Account) AND Level__c = 'Primary' AND LastName LIKE 'test%'];
system.debug(limits.getCpuTime());
system.debug(conList.size());
で、結果です。

とりあえずこれが基準になります。
ではどんどんいきます。
バインド変数をつけてみる
バインド変数で動的に値が入ってきたと想定して同じ値を取得するのにどう違うのかをみてみました。
実行したのは下記です。
List<Contact> conList = [SELECT Id FROM Contact WHERE AccountId IN :[SELECT Id FROM Account] AND Level__c = :'Primary' AND LastName LIKE :'test%'];
system.debug(limits.getCpuTime());
system.debug(conList.size());
IN句の()をSOQLでバインドにしてます。※ほんとならもっと動的にするんですが実験のためなのでご了承ください。
他にも文字列の前にバインド変数の:を追加しています。
で結果が下記です。

ん、ちょっと早くなった?
誤差の範囲か・・・?
ほかもやってみます。
ズボラせずにちゃんと変数に入れたバインド変数でやってみる
さっきは完全にズボラだったのでちゃんと変数を用意した上でやります。
List<Account> accList = [SELECT Id FROM Account];
String primary = 'Primary';
String test = 'test%';
List<Contact> conList = [SELECT Id FROM Contact WHERE AccountId IN :accList AND Level__c = :primary AND LastName LIKE :test];
system.debug(limits.getCpuTime());
system.debug(conList.size());
さて、結果ですが。

劇的に変わることもなく、、、なんなら直接入れてる方がはやいじゃんって話がでてきて
焦っております。
バインド変数なしのDatabaseクエリを使ってみる
次は最初に使ったSOQLをDatabaseクエリを使って実行してみました。
String query = 'SELECT Id FROM Contact WHERE AccountId IN :accList AND Level__c = \'' + 'Primary' + '\' AND LastName LIKE \'' + 'test' + '%\'';
List<Contact> conList = Database.query(query);
system.debug(limits.getCpuTime());
system.debug(conList.size());

驚くほどの無意味な実験になりそうです今回。
何を使っても1万件も取得するとなったら同じなのか。。。
バインド変数ありのDatabaseクエリを使ってみます
もしここまで読んでいただいた方には本当に申し訳ないので、
使ってみますと敬語になりましたが、、、
最後は下記のコードで試してみました。
List<Account> accList = [SELECT Id FROM Account];
String primary = 'Primary';
String test = 'test%';
String query = 'SELECT Id FROM Contact WHERE AccountId IN :accList AND Level__c = \'' + primary + '\' AND LastName LIKE \'' + test + '%\'';
List<Contact> conList = Database.query(query);
system.debug(limits.getCpuTime());
system.debug(conList.size());

これだけCPUTimeが長かったですが、TimeLineみても他とそんなに変わらないし。。。
正直そこまで変わらないのか。。。
まとめ
大した記事がかけず申し訳ないですが、今回の結果としてはほぼどれも同じという結果でした。
うーん、テストケースがよくなかったかな。。。
ただ今回の実験をするにあたり、SOQLインジェクションなどの考慮もというのもまた知識としてありましたので、
次はそこの記事でもかければと思います。
最後までご覧いただき、ありがとうございました!
コメント