【问题标题】:Inserting large dataset from CSV file with CI Model使用 CI 模型从 CSV 文件中插入大型数据集
【发布时间】:2022-01-06 11:06:51
【问题描述】:

我有一个包含 500 万行的 CSV 文件。我正在使用来自 thephpleague.com 的 CSV 库。它使用生成器,因此逐行读取文件。所以阅读不会有任何问题。

然而,我想使用 CI 模型将它们保存到数据库中,因为我需要确保数据完整性可以。所以我想使用模型的验证器,beforeInsert 回调等。所以问题不是如何将数据插入数据库,而是如何通过使用模型处理插入数据。

这是我的代码:

namespace App\Util;

use App\Models\TestModel;
use League\Csv\Reader;

class CSV
{
    public function readData(string $filePath, array $headers = [])
    {
      
        $filePath = ROOTPATH.'test.5mn.csv';

        $maxExecutionTime = ini_get("max_execution_time");
        ini_set('max_execution_time', 300);

        $reader = Reader::createFromPath($filePath, 'r');
        $reader->setHeaderOffset(0); //set the CSV header offset
        $reader->skipEmptyRecords();

        if (true === empty($headers)) {
            $headers = $reader->getHeader();
        }

        $records = $reader->getRecords($headers);

        $isGoodToGo = true;
    
        foreach ($records as $record) {
            if ($this->isEmptyWithNullValues($record)) {
                continue;
            }

            if ($this->isEmptyWithBlankString($record)) {
                continue;
            }

            $model = model(TestModel::class);
            $model->save([
                'item_type' => $record["Item Type"],
                'sales_channel' => $record["Sales Channel"],
                'total_profit' =>  $record["Total Profit"],
            ]);
            log_message('error', '#'.$model->getInsertID() . ' saved');
            $model = null;
        }

        ini_set('max_execution_time', $maxExecutionTime);

        return $isGoodToGo;
    }
    ....
} 

在控制器上我这样称呼:

public function index()
{
    $test = new CSV();
    $test->readData('path', []);
    dump('EXIT');
} 

但我在一定数量的记录后给出了 php 内存错误。在开发环境中,在抛出内存错误后,它只能保存 123456 条记录。在生产中,它保存了 253321 条记录,然后抛出内存错误。

我认为某处存在开销,但我不是专家。在模型、连接或任何地方,有没有一种方法可以让我flush 内存.. 我在想 CI 即使在生产环境中也能保留一些数据。任何想法都会非常有帮助。谢谢。。

供参考;错误信息:

CRITICAL - 2022-01-06 11:48:09 --> 允许的内存大小为 134217728 字节已用尽(尝试分配 67108872 字节)
#0【内部函数】:CodeIgniter\Debug\Exceptions->shutdownHandler()
#1 {主要}

【问题讨论】:

标签: php csv model-view-controller bigdata codeigniter-4


【解决方案1】:

您的 csv 文件有多大(以 MB 为单位)?

原因是,如果您的内存限制为 128mb,而您的文件为 100mb(根据您的文件名,我推测您那里有数百万条记录),那么您仅通过加载 csv 文件就已经消耗了大部分内存。

我相信除了将内存限制设置为 -1 并交叉手指之外,与代码没有太大关系。它可能会再次工作或崩溃。

我的建议和我会怎么做?

无论如何,不​​应将这么多的记录一次性插入数据库。分批完成工作是最佳实践。当您有 3000 万或 10000 万条记录时,批次仍然可以工作,但不是这一条。

【讨论】:

  • 文件以 GB 为单位。然而,“它使用生成器,因此逐行读取文件。因此读取不会导致任何问题。”
【解决方案2】:

我在 CI 论坛上得到了答案。 CI 项目负责人提到:

"过去我不得不这样做。我在那里处理它的方式是使用 LOAD DATA 命令将 CSV 加载到一个新的临时表中。然后循环遍历临时表进行验证在将数据插入正确的表之前对数据进行规范化。 而且,是的,chunk() 是一个完美的用例,一旦你将它放在临时表中。"

在此处发布以供将来参考。谢谢。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-29
    • 2021-09-20
    • 2014-09-30
    • 2017-07-13
    • 1970-01-01
    相关资源
    最近更新 更多