read_csv - python逐行写入csv




导入大型CSV文件的最佳做法 (7)

FWIW以下步骤导致我的LOAD DATA INFILE速度LOAD DATA INFILE

SET FOREIGN_KEY_CHECKS = 0;
SET UNIQUE_CHECKS = 0;
SET SESSION tx_isolation='READ-UNCOMMITTED';
SET sql_log_bin = 0;
#LOAD DATA LOCAL INFILE....
SET UNIQUE_CHECKS = 1;
SET FOREIGN_KEY_CHECKS = 1;
SET SESSION tx_isolation='READ-REPEATABLE';

见文章

我的公司每个月都会获得一组包含银行帐户信息的CSV文件,我需要将其导入数据库。 其中一些文件可能非常大。 例如,一个是大约33MB和大约65,000行。

现在我有一个symfony / Doctrine应用程序(PHP),它读取这些CSV文件并将它们导入数据库。 我的数据库有大约35个不同的表,在导入过程中,我将这些行拆分为组成对象并将它们插入到数据库中。 这一切都很漂亮,除了它很 (每行大约需要四分之一秒),它使用了大量的内存。

内存使用非常糟糕,我必须拆分我的CSV文件。 一个20,000行的文件几乎没有进入。当它接近结束时,我的内存使用率达95%。 导入该65,000行文件根本不可能。

我发现symfony是一个用于构建应用程序的特殊框架,我通常不会考虑使用其他任何东西,但在这种情况下,我愿意以性能的名义将所有的先入之见抛弃窗外。 我不承诺任何特定的语言,DBMS或任何东西。

Stack Overflow不喜欢主观问题,所以我会尝试尽可能不主观:对于那些你不仅仅有意见但有经验导入大型CSV文件的人 ,你使用了哪些工具/做法过去那已经成功了吗?

例如,您是否只使用Django的ORM / OOP并且您没有遇到任何问题? 或者您是否将整个CSV文件读入内存并准备一些庞大的INSERT语句?

同样,我不仅仅是一个意见,而是一些过去实际上对你有用的东西。

编辑:我不只是将85列CSV电子表格导入一个85列数据库表。 我正在将数据规范化并将其放入几十个不同的表中。 出于这个原因,我不能只使用LOAD DATA INFILE (我正在使用MySQL)或任何其他只读取CSV文件的DBMS功能。

此外,我不能使用任何Microsoft特定的解决方案。


大约两周前,我遇到了同样的问题。 我写了一些.NET来做ROW BY ROW插入,根据我的计算得到的数据量,用这种方式花费大约一个星期。

因此,我使用字符串构建器创建一个巨大的查询并将其一次性发送到我的关系系统。 它从用了一个星期到用了5分钟。 现在我不知道你正在使用什么样的关系系统,但是如果有大量的查询,你可能需要调整你的max_allowed_pa​​cket参数或者类似的。


您可以使用Mysql LOAD DATA INFILE statemnt,它允许您从文本文件中读取数据并将文件的数据快速导入数据库表中。

LOAD DATA INFILE '/opt/lampp/htdocs/sample.csv' INTO TABLE discounts FIELDS TERMINATED BY ',' ENCLOSED BY '"' LINES TERMINATED BY '\n' IGNORE 1 ROWS (title,@expired_date,discount) SET expired_date = STR_TO_DATE(@expired_date, '%m/%d/%Y');

http://dev.mysql.com/doc/refman/5.5/en/load-data.html了解更多信息: http://dev.mysql.com/doc/refman/5.5/en/load-data.htmlhttp://dev.mysql.com/doc/refman/5.5/en/load-data.htmlhttp://www.mysqltutorial.org/import-csv-file-mysql-table/


您可以使用生成器来准备内存高效的文件。 下面的小片段可能会对你有所帮助。

#Method
public function getFileRecords($params)
{
    $fp = fopen('../' . $params['file'] . '.csv', 'r');
    //$header = fgetcsv($fp, 1000, ','); // skip header

    while (($line = fgetcsv($fp, 1000, ',')) != FALSE) {
        $line = array_map(function($str) {
            return str_replace('\N', '', $str);
        }, $line);

        yield $line;
    }

    fclose($fp);

    return;
}

#Implementation
foreach ($yourModel->getFileRecords($params) as $row) {
    // you get row as an assoc array;
    $yourModel->save($row);
}

我也需要不时地执行此操作(导入大型非标准化CSV,其中每行创建十几个相关的DB对象)所以我编写了一个python脚本,我可以在其中指定哪些内容以及它们如何相关。 然后该脚本只生成INSERT语句。

这是: csv2db

免责声明:在数据库方面,我基本上是一个菜鸟,因此可能有更好的方法来实现这一目标。


我正在读取一个CSV文件,该文件有近1M条记录和65列。 在PHP中处理的每1000条记录中都有一条进入数据库的大胖MySQL语句。 写作不花时间。 这是解析。 用于处理此未压缩的600MB文件的内存大约为12 MB。


请原谅我,如果我没有正确理解你的问题,但似乎你只是想把大量的CSV数据存入SQL数据库。 您是否有任何理由要使用Web应用程序或其他代码将CSV数据处理为INSERT语句? 我已成功使用SQL Server Management Studio和使用BULK INSERT语句将大量CSV数据导入SQL Server Express(免费版)。 一个简单的批量插入看起来像这样:

BULK INSERT [Company].[Transactions]
    FROM "C:\Bank Files\TransactionLog.csv"
    WITH
    (
        FIELDTERMINATOR = '|',
        ROWTERMINATOR = '\n',
        MAXERRORS = 0,
        DATAFILETYPE = 'widechar',
        KEEPIDENTITY
    )
GO




import