【问题标题】:PHP - Parse and validate text file data and import it into mysql databasePHP - 解析和验证文本文件数据并将其导入 mysql 数据库
【发布时间】:2018-05-07 21:02:55
【问题描述】:

我正在使用 php-resque 来解析和验证大文件中的数据,然后将该数据导入 mysql 数据库。

我已经知道 LOAD DATA INFILE 可用于将文本文件中的行读取到表中,但不执行任何验证。

我的数据库结构:

ItemsFile表格:

id  filename  fileepath  valid_items invalid_items processed_items  processed

项目表:

id  uid  item file_id created_at

我的 Resque 作业类如下所示:

php-resque 派生出一个子进程并实例化 ItemsFileProcessor 类

  1. setUp() 被调用
  2. perform() 被调用
/**
* Read and validate items form a file, and store them in a database.
*/

class ItemsFileProcessor {

    //ItemsFile Model instance
    private $items_file = null;

    //Item Model instance
    private $item = null;

    //retrieved from ItemsFile table.
    private $file = null;

    public function __construct() {
        $this->items_file = new ItemsFile();
        $this->item       = new Item();
    }

    public function setUp() {

        if (isset($this->args['file_id'])) {

            //get file from ItemsFile Table by id.
            $this->file = $this->items_file->getFile($this->args['file_id']);

            if (empty($this->file)) {

                //End job processing if file does not exist.
                exit(-1);

            }

        }
    }

    function perform() {

        //NodeJs, socket.io, redis, broadcasting system
        EventBroadcaster::broadcast('app-jobs-channel', 'file_processing_started');

        $processed_items = 0;
        $valid_items     = 0;
        $invalid_items   = 0;

        //item validation class instance
        $item_validator = new ItemValidator();

        try {

            $tmp_file = new SplFileObject($this->file->filepath);

            //Read items from file, and validate each item.
            while ($tmp_file->valid()) {
                $line = trim($tmp_file->fgets());
                if ($line !== '') {
                    if ($item_validator->isValid($line, new ItemValidationRule())) {

                        //store item in Item table.
                        $this->item->create([
                                'uid'     => 'foo',
                                'item'    => $line,
                                'file_id' => $this->file->id,
                            ]);

                        $valid_items++;

                    } else {

                        $invalid_items++;

                    }

                    $processed_items++;

                }
            }

            //update ItemsFile Table record
            $this->items_file->update(
                $this->file->id,
                [
                    'processed_items'  => $processed_items,
                    'valid_items'      => $valid_items,
                    'invalid_items'    => $invalid_items,
                    'processed'        => 'Processed',
                ]
            );

            EventBroadcaster::broadcast('app-jobs-channel', 'file_processing_completed');

        } catch (LogicException $exception) {

            //broadcast failure.
            EventBroadcaster::broadcast('app-jobs-channel', 'file_processing_failed');
            Logger::getInstance()->log('ProcessContactFile Exception: '.$exception->getMessage(), Logger::LOGTYPE_ERROR);

            exit(-1);

        }
    }

}

我的问题:

  • 处理文件耗时过长
  • Mysql 必须一一处理所有的插入请求。 LOAD DATA INFILE 更快。

我的问题:

有没有办法对此进行优化,或者以某种方式引入 LOAD DATA INFILE。

【问题讨论】:

    标签: php mysql performance php-resque


    【解决方案1】:

    在使用 PHP 管理文件时,您可能会遇到许多性能问题。然后,我建议您使用 SHELL 来解析文件并返回一个字符串(表示您对所有插入的一般请求)。从现在开始你只需要执行这个请求。

    如果不清楚,可以提供帮助。

    【讨论】:

    • 如果你还想用 PHP 做,你可以尝试先构建你的请求。在这之后你执行它。
    • 我需要使用一些复杂的验证规则来验证文件的每一行,这些规则我已经在我的 ItemValidator 模块中的 php 中实现了,所以我不能只将它移植到外壳脚本。 PS:如果可能的话,我需要一个实际的实现。
    猜你喜欢
    • 1970-01-01
    • 2012-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-16
    • 1970-01-01
    • 2012-11-14
    相关资源
    最近更新 更多