function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
ikouikou 

1万件を超えるレコードのカウント方法

ガバナー制限としてSOQLにて取得できるレコード数の上限は1万件まで(Trigger,Testは除く)というのが定められています。

(Total number of records retrieved by SOQL queries 10,000)

 

これはSOQLのCount()でも適用されるようです。

 

Integer i = [SELECT Count() FROM Account];

 

 あるオブジェクトのレコード数を出したい場合で、その数が1万件を超える可能性がある場合、

このガバナーを回避して数を取得する方法があるでしょうか?

 

LovelyWankoLovelyWanko

うーーん、ガバナ制限は回避するのはおそらく。。。 (ヾノ・∀・`)ムリムリ

 

StandardSetController 
クラスを利用すれば 5千万件まではカウントできると思われます。

以下のページを参考になるかもしれません。

 

 http://www.salesforce.com/us/developer/docs/pages/Content/apex_pages_standardsetcontroller.htm#kanchor889

 

 

StandardSetControllerの中

getResultSizeメソッドがあるのこちらを利用してみるっす。

 

サンプルコードです。

 

Visualforceページ:Sample

 

<apex:page controller="TempController">
<apex:form>
<apex:commandButton action="{!TestExec}" value="TestMethodCall" reRender="SizeSection"/>
</apex:form>
<p>
<apex:outputPanel id="SizeSection">
配列サイズ = <apex:outputText value="{!DataSize}" />
</apex:outputPanel>
</p>
</apex:page>

 

 コントローラ:TempController

 

public class TempController {

public Long DataSize{get; set;}

public PageReference TestExec() {
ApexPages.StandardSetController ssc =
new ApexPages.StandardSetController(Database.getQueryLocator([SELECT name FROM Contact]));
DataSize = ssc.getResultSize();

return null;
}

}

 

 5千万件を超える場合は Ajax(WebservicesAPI)の併用を検討してみはどうでしょうか?

 

 

 

 

Message Edited by LovelyWanko on 03-28-2010 12:47 AM
ikouikou

LovelyWankoさん

 

頂いたSampleをAccountが1万件以上ある組織で実行したところ、ガバナーのエラーが発生しました。

 

たしかにドキュメントにはDatabase.QueryLocatorにて5000万件まで取得可能みたいなことが書かれていますが、

これって、あくまでガバナーに触れなければ5000万件まで可能ということじゃないでしょうか?

 

例えばBatch Apexのstartメソッドで返す時の値とか。

 

AJaxに関しては、これを使用すると今度はAPIコール数の問題とか出てくるんで、使いどころを見極める必要がありそうです。

 

 

そうするとApexのみで考えるとやはり1万件の問題は解決しないわけですが。。

 

今のところ「カウントしたいオブジェクトの総数を管理する別テーブルを作成してTriggerで更新」

というようなイケてない方法しか思いつきません。。

 

まぁ、何か作っていて問題が発生しているわけではなく、あくまで気になっただけの問題なので緊急性はないのですが。

LovelyWankoLovelyWanko

:smileysurprised: Database.QueryLocatorを通常のApexクラスで利用しても1万件を超える

とエラーになってしまうのですね!

BatchApex のときが有効なのですね。

 

Ikouさんの案:カスタムオブジェクトなどにTriggerで都度カウントしておきQueryで全件のカウント

を取得すると ⇒ な~るほど the world。(ちょっと古い :robotsurprised:)

 

苦肉の策として思いついたのは、BatchApexを非同期で呼び出してBatchApexの処理結果を

カスタムオブジェクトに書き出してポーリングなどをかけてその結果に書き出されたカスタムオブジェクト

から値を取得する感じですか。。。:smileysad:

 

 

 

 

Message Edited by LovelyWanko on 04-01-2010 02:39 AM
Message Edited by LovelyWanko on 04-01-2010 02:40 AM
HikeyHikey

http://hikey.web.fc2.com/discussion_boards/partnersmall.xml

1万件以上をApexコントローラから取得する方法を考えた見たyo :smileysurprised:

 

ApexコントローラからSalesforceサーバに対してCallOutを行う方法 ヾ(・∀・o)ノダー!!

以下の手順で行ってみるyo (`・ω・´)

 

1.リモートサイトの設定

ログインURL と API で使うURL(LoginResult でReturnされるURL)を設定

σ(・Д・`) の場合 ログインURL:https://www.salesforce.com

APIのURL(ログインすると帰ってくるAPI利用サーバ):https://na7-api.salesforce.com

 

2.WSDLからApexクラスを生成する!!。

SFのParner.wsdlを利用。ただしそのままだとApexクラスが大きくなりすぎてエラーになるのでQueryとログインに必要そうな定義だけに削る。

 

3.後はCallOutを実装するだけ

 

縮小版PartnerWSDL:

http://hikey.web.fc2.com/discussion_boards/partnersmall.xml

 

Apexコントローラ:

 

 

public class QueryCallOutSampleController {

    partnerSoapSforceCom.Soap bind = new partnerSoapSforceCom.Soap();
    
    public QueryCallOutSampleController(){
        
    }

    public PageReference Query() {
        partnerSoapSforceCom.LoginResult result = bind.login('<loginId>', '<password>');

        bind.endpoint_x = result.serverUrl;
        partnerSoapSforceCom.SessionHeader_element sh = new partnerSoapSforceCom.SessionHeader_element();
        sh.sessionId = result.sessionId;
	//ログインしない場合は自分のセッションIDを利用
	//sh.sessionId = UserInfo.getSessionId(); 

        bind.SessionHeader = sh;
        
        partnerSoapSforceCom.QueryResult qresult = bind.query('Select count() from Account');
        
        return null;
    }


}

 

 

 

 

呼び出しVisualforce:

 

<apex:page controller="QueryCallOutSampleController">

  <apex:form >
    <apex:commandButton action="{!Query}" value="CallOut"/>
  </apex:form>

</apex:page>

 

ikouikou

LovelyWankoさん

Hikeyさん

 

すみません、返事が遅くなりました!

仕事でJavaScriptが動作しない環境にいるのでDiscussionBoardsを見ることができず。。。

というグチはさておき。

 

お二人とも方法を考えて頂き、ありがとうございます。

 

特にHikeyさん案のコントローラからCallOutを行うという方法は考えもしませんでした。

ただ、私の知識不足でぱっと見で理解できないので、時間があるときにちょっと検証してみたいと思います。