3

CFWheelsを使用して大量のレコードをデータベースに保存することに問題があります。次に例を示します。

<cfloop from="1" to="10000" index="i">
 <cfset var newUser = model("user").new()>
 <cfset newUser.name = "Test"&i>
 <cfset newUser.save()>
</cfloop>

これにより、java.lang.OutOfMemoryErrorが発生します

この問題を解決する方法を教えてください。

4

3 に答える 3

5

OOMにつながる複数のデータベース呼び出しをループすることは、ColdFusionの既知のバグです。幸い、回避策があります。を使用してください<cfthread/>。次のようにコードを変更できるはずです。

<cfloop from="1" to="10000" index="i">
 <cfset threadName = "thread" & createUuid()>
 <cfthread name="#threadName#">
  <cfset var newUser = model("user").new()>
  <cfset newUser.name = "Test"&i>
  <cfset newUser.save()>
 </cfthread>
 <cfthread action="join" name="#threadName#">
</cfloop>

この状況では、スレッドをその副作用のためだけに使用し、ヒープに保持されないように別のコンテキストで実行しています。したがって、スレッドを宣言した直後の結合であるため、実際には何も並行して実行されていません。

于 2011-06-01T12:07:26.223 に答える
1

ガベージコレクターの実行を試みることができます:http: //www.beetrootstreet.com/blog/index.cfm/2009/6/25/Clearing-ColdFusion-memory-using-garbage-collection-when-memory-gets-low

于 2011-06-01T12:41:15.550 に答える
0

ここでは、かなり非効率的なことが 2 つあります。まず、1,000 個のuserオブジェクトを生成しますが、これは ColdFusion で 1 回の要求で行うのはあまり良い考えではありません。2 つ目は、1,000 件のデータベース クエリを実行していることです。これは、どのプログラミング言語でも実行するのは良い考えではありません。

このような場合にモデル オブジェクトを使用するのをやめて、ロジックを 1 つのデータベース クエリに凝縮する方法を見つけます。Wheels の ORM は一般的に非常に便利ですが、このような状況では限界があります。

たとえば、SQL Server 2008 を使用している場合は、userモデル内でこれを実行して、すべてを 1 回の呼び出しで保持できcfqueryます。

<cffunction name="batchCreate">
    <cfquery datasource="#get('dataSourceName')#">
        INSERT INTO
            #this.tableName()# (#this.columnNameForProperty("name")#)
        VALUES
            <cfloop from="1" to="10000" index="i">
                (<cfqueryparam cfsqltype="cf_sql_varchar" value="Test#i#">)
                <cfif i lt 10000>,</cfif>
            </cfloop>
    </cfquery>
</cffunction>

もちろん、MySQL または別のデータベース エンジンを使用している場合、クエリは異なって見えます。

于 2011-06-02T12:30:16.840 に答える