簡體   English   中英

使用 PHP/MySQL 導出大型 CSV 數據的最佳方法是什么?

[英]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 創建一個空文件

  • 從查詢結果集中單獨讀取每個數據行
  • 直接寫入 php://output
  • 然后閱讀下一行,依此類推;

而不是構建任何大型數組或在內存中構建 csv

簡短描述:將數百行的包導出到 CSV 重用變量,因此內存壓力將保持較低。 您不能將整個 mysql 表放入數組中(然后放入 CSV 文件),這是主要問題

詳細說明:嘗試使用此方法導出一個帶有列名的大表(我使用過它,效果很好,它也可以改進、壓縮和優化,但 .. 稍后):

  1. 打開 CSV 文件(標題、 fopen等)
  2. 用列名定義一個數組: fputcsv($f, $line, $delimiter);
  3. 獲取您想要的 id 列表(不是整行,只有 id): SELECT id FROM table WHERE condition ORDER BY your_desired_field ASC -> here you have $ids
  4. $perpage = 200; // how many lines you export to csv in a pack;
  5.  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
  6. 關閉 CSV

因此,您將遍歷整個結果表,獲取 200 行並將它們寫入 CSV,該 CSV 將等待打開,直到您寫入所有行。 您需要的所有內存都用於 200 行,因為您將重新寫入變量。 我相信它可以以更好的方式完成,但我花了幾個小時並沒有找到解決方案; 此外,它受我的架構和應用程序需求的輕微影響,這就是我選擇此解決方案的原因。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM