2010-03-03 106 views
6

我想創建一個使用CakePHP的XML站點地圖,從當前有超過50,000條記錄的表中創建,每個記錄等同於站點地圖中的URI。現在我面臨的問題是CakePHP的運行我的內存不足而產生的,原因有二:CakePHP建議迭代一個巨大的表並生成一個站點地圖?

  1. 一個find('all')是建立一整套50000項的URI的一個巨大的關聯數組。
  2. 因爲我不想從控制器本身輸出HTML,我能傳送包含URI,優先級,變化頻率等關聯數組,該視圖與$this->set()電話 - 這又是巨大的,含50000指數。

是否有可能在遵循MVC和CakePHP指南的情況下執行此操作?

回答

2

你確定你必須在50.000記錄運行內存不足?即使一行的大小是1K(非常大),你也不得不處理大約50MB的數據?我的P1有足夠的內存來處理。在php.ini中設置memory_limit高於默認值。 (也考慮調整max_execution_time。)

另一方面,如果您認爲數據集太大並且處理過於耗費資源,則不應該動態地爲頁面提供服務,這是完美的DDoS誘餌。 (至少我會緩存它。) 您可以安排一個cron作業,每隔X小時通過一個服務器端腳本重新生成頁面,這個腳本不受MVC一次向視圖提供所有數據的懲罰,它可以工作依次排列。

+0

站點地圖在我的本地開發箱上工作得很好。一旦我部署到我的共享主機,我有非常有限的內存,它爆炸。這正是我所想的,只是想仔細檢查一下,並確保我這樣做,因爲沒有CakePHP/MVC選項。謝謝! – 2010-03-04 04:30:04

1

你試過unBindModel(如果你有關係)......

每當我需要做的CakePHP中的巨大查詢我只是用「常規」 MySQL的函數一樣的mysql_query,mysql_fetch_assoc等快很多,不乏記憶...

+0

這是一個SELECT表。看起來像老派的MySQL是有效的和唯一的方法,但是到那時我已經走出了CakePHP。我仍然有如何渲染計算關聯數組的問題。 – 2010-03-03 13:49:15

3

這周我有類似的問題,和整個Containable行爲絆倒了。這可以讓你減少任何關係相關的查詢(如果有的話)。

最好的解決辦法是,以編程方式使用LIMIT and OFFSET,並遍歷記錄小塊在同一時間。這可以避免您一次將50K記錄填充到內存中。

+0

感謝您的回覆。我沒有任何相關的表,查詢或多或少是一個簡單的'SELECT'操作。解決多個查詢是我想避免的。另外,即使我這樣做,我仍然如何將數據傳輸到視圖? – 2010-03-03 13:45:22

+0

你會在同一視圖中顯示所有50k記錄嗎?如果不是這樣,大多數分頁模式在極限/偏移量查詢中運行良好。 如果您必須一次顯示所有內容,可以挖掘您的php.ini(如果您有管理員訪問您的服務器)並將memory_limit更改爲更高的值。這可能通過find('all)來解決你的內存問題。 如果您的表格有很多字段,請使用'字段'值來縮小必要內容(如另一評論中所述)。 – bojo 2010-03-04 01:54:58

2

發現(「全部」)是太貪婪,你將有更具體的,如果你不想耗盡內存。

如上所述,請使用Containable行爲。如果你只需要從表中,結果(無關聯的表),以及只有幾個字段,這樣一個更明確的查詢應該會更好:

$results = $this->YourModel->find('all', array(
    'contain' => false, 
    'fields' => array('YourModel.name', 'YourModel.url') 
); 

你也應該考慮增加一個HTML緩存機制(CakePHP的有一個內置的或使用一個suggested by Matt Curry)。

當然,這將是一個緩存版本,而不是完全最新到列表中。如果需要更多控制,可以使用模型的afterSave/afterDelete回調將結果始終保存在Cake緩存中(使用Cache::write),以更新緩存的值並從此處重新創建緩存的xml文件。

+0

具體來說,查看find()的「fields」參數。 – 2010-03-03 16:47:06

4

我知道這個問題是舊的,但對於真正巨大的查詢,我仍然沒有很好的解決方案。

要遍歷一個巨大的結果集,你可以使用DboSource方法。

首先得到DBO

$dbo = $this->Model->getDataSource(); 

構建查詢

$sql = $dbo->buildStatement($options); 

然後通過結果

if ($dbo->execute($sql)) 
{ 
    while ($dbo->hasResult() && $row = $dbo->fetchResult()) { 
     // $row is an array with same structure like find('first') 
    } 
} 
+0

從CakePHP 2.4.4開始,'$ dbo-> buildStatement'需要兩個參數。此外,'$ dbo-> buildStatement'只返回一個無表名的無效SQL。在挖掘源代碼後,我使用了'$ this-> generateAssociationQuery($ model,null,null,null,null,$ queryData,false,$ null);' – VCD 2014-03-24 04:17:08