我有一個mysql表,其中每個記錄可以有無限的自定義字段(EAV模型,這並不重要),每個字段可以有無限的選項,每個選項可以有無限的價值。
現在我正在嘗試構建一個導出工具,將導出所有這些自定義字段的值,即:每個字段的name =>值對。這不是重要的部分,它只是爲了強調我們正在討論大量針對單個記錄的mysql查詢,並且導出的大小會非常大。導出大的CSV文件
對於每一行從我的主表,我必須做的大約100單獨的SQL查詢來獲得的油田,它們的選項和字段選項的值。這些查詢速度相當快,因爲它們都使用正確的索引,但我們仍然在談論對單個記錄的100個查詢,並且我希望在我的主表中有大約5萬條記錄只是爲了開始。
現在,我要做的就是:
set_time_limit(0);
ini_set('memory_limit', '1G');
ini_set("auto_detect_line_endings", true);
$count = $export->count();
$date = date('Y-m-d-H-i-s');
$fileName = CHtml::encode($export->name) .'-'. $date . '.csv';
$processAtOnce = 100;
$rounds = round($count/$processAtOnce);
header("Content-disposition: attachment; filename={$fileName}");
header("Content-Type: text/csv");
$headerSet = false;
for ($i = 0; $i < $rounds; ++$i) {
$limit = $processAtOnce;
$offset = $i * $processAtOnce;
$rows = $export->find($limit, $offset);
if (empty($rows)) {
continue;
}
$outStream = fopen('php://output', 'w');
if (!$headerSet) {
fputcsv($outStream, array_keys($rows[0]), ',', '"');
$headerSet = true;
}
foreach ($rows as $row) {
fputcsv($outStream, array_values($row), ',', '"');
}
echo fgets($outStream);
fclose($outStream);
}
基本上我指望所有的記錄和我「分頁」他們用於出口,然後通過網頁運行一次,以avoin裝載了太多的SQL結果。
我想知道這是否是一種有效的方法?有什麼想法嗎?
我的替代方法是計算所有的記錄,將它們分成「頁」,併爲每個頁面做一個Ajax請求(先前的請求已經被成功地進行了後稱爲遞歸函數)。在執行ajax請求時,可能會一次處理1k條記錄(這些1k也會像上例中一樣拆分,例如在內部運行10次(例如,使用100個結果),將它們寫入臨時目錄(如part-1.csv,部分2.csv),並在最後處理所有記錄時,從包含所有csv部分的文件夾中創建一個存檔,並強制瀏覽器下載它,然後將其從服務器中刪除(window.location.href最後ajax調用)。
這是一個很好的替代上述?
請注意,我的目標是要限制使用內存,這就是爲什麼我認爲第二個方法將有助於我更多的量。
請讓我知道您的想法。
謝謝。
如果您的數據結構,你爲什麼不選擇JSON格式而不是CSV?只是一個「第一個想法」... – Powerslave
它將用於OpenOffice/Office,並在其他只支持csv的系統中導入,而json不是這個選項,它必須是csv :) – Twisted1919