[英]What is the best approach to export large CSV data using PHP/MySQL?
我正在處理一個項目,我需要從包含近 10k 行的數據庫中提取數據,然后將其導出為 CSV。 我嘗試了下載 CSV 的正常方法,但即使我們已經將 memory_limit 設置為 256MB,我也總是遇到內存限制問題。
如果你們中有人遇到過同樣的問題,請分享您對最佳解決方案或方法的想法。
真的很感謝你的想法伙計們。
這是我的實際代碼:
$filename = date('Ymd_His').'-export.csv';
//output the headers for the CSV file
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header('Content-Description: File Transfer');
header("Content-type: text/csv");
header("Content-Disposition: attachment; filename={$filename}");
header("Expires: 0");
header("Pragma: public");
//open the file stream
$fh = @fopen( 'php://output', 'w' );
$headerDisplayed = false;
foreach ( $formatted_arr_data_from_query as $data ) {
// Add a header row if it hasn't been added yet -- using custom field keys from first array
if ( !$headerDisplayed ) {
fputcsv($fh, array_keys($ccsve_generate_value_arr));
$headerDisplayed = true;
}
// Put the data from the new multi-dimensional array into the stream
fputcsv($fh, $data);
}
// Close the file stream
fclose($fh);
如果您確實必須在 PHP 中進行處理,則需要使用 MYSQL 的 limit 命令來獲取數據的子集。 每次只抓取一定數量的行,將它們寫入文件,然后抓取下一組。
您可能需要對查詢循環中的一些變量運行 unset()。 關鍵是不要一次在內存中有太多龐大的數組。
如果您要抓取整個合並表,請按插入日期升序對它們進行排序,以便第二次抓取將獲得任何更新的項目。
正如此評論中所解釋的: https : //stackoverflow.com/a/12041241/68567使用 mysqldump 可能是最好的選擇。 如果需要,您甚至可以使用 exec() 命令通過 php 執行此操作,如下所述: php exec() - mysqldump 創建一個空文件
而不是構建任何大型數組或在內存中構建 csv
簡短描述:將數百行的包導出到 CSV 重用變量,因此內存壓力將保持較低。 您不能將整個 mysql 表放入數組中(然后放入 CSV 文件),這是主要問題
詳細說明:嘗試使用此方法導出一個帶有列名的大表(我使用過它,效果很好,它也可以改進、壓縮和優化,但 .. 稍后):
fopen
等)fputcsv($f, $line, $delimiter);
SELECT id FROM table WHERE condition ORDER BY your_desired_field ASC
-> here you have $ids
$perpage = 200; // how many lines you export to csv in a pack;
for ($z=0; $z < count($ids); $z += $perpage) { $q = "SELECT * FROM table WHERE same_condition ORDER BY your_desired_field ASC LIMIT " . $perpage . " OFFSET " . $z // important: use the same query as for retrieving ids, only add limit/offset. Advice: use ORDER BY, don't ignore it, even if you do not really need it; $x = [execute query q] for ($k=0; $k < count($x); $k++) { $line = array($x[$k]->id, $x[$k]->field1, $x[$k]->field2 ..); fputcsv($f, $line, $delimiter); } } // end for $z
因此,您將遍歷整個結果表,獲取 200 行並將它們寫入 CSV,該 CSV 將等待打開,直到您寫入所有行。 您需要的所有內存都用於 200 行,因為您將重新寫入變量。 我相信它可以以更好的方式完成,但我花了幾個小時並沒有找到解決方案; 此外,它受我的架構和應用程序需求的輕微影響,這就是我選擇此解決方案的原因。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.