2011-06-01 33 views
3

我在使用CFWheels將大量記錄保存到數據庫時遇到了問題。這裏有一個例子:保存大量記錄時java.lang.OutOfMemoryError

<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

請幫助我如何解決這個問題。

回答

0

有一對夫婦是非常低效的東西會在這裏。首先,它會生成1,000 user對象,這在ColdFusion中的單個請求中並不是一個好主意。其次,它運行着1,000個數據庫查詢,這在任何編程語言中都不是一個好主意。

我會停止使用這種情況下的模型對象,並找出如何將邏輯壓縮成單個數據庫查詢。 Wheels中的ORM通常非常有用,但它在這種情況下有其侷限性。

例如,如果你使用SQL Server 2008中,你可以做到這一點你user模型中一個呼叫中保持一切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或其他數據庫引擎。

5

Looping over multiple database calls leading to OOM is a known ColdFusion bug。幸運的是,有一種解決方法,使用<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> 

在這種情況下,您使用的線程僅用於其副作用,在不同的上下文中運行,這樣它不會保留在堆上。因此,聲明線程後立即加入權利,所以它並不實際上並行運行任何東西。

+0

這是Adobe的官方解決方法嗎? – Henry 2011-06-01 16:50:42

+1

@亨利:http://cfbugs.adobe.com/cfbugreport/flexbugui/cfbugtracker/main.html#bugId=85736是記錄的錯誤。 AFAIK Adob​​e尚未確認或評論此問題。在實踐中,這是相對罕見的。 – orangepips 2011-06-01 17:20:39