我有一系列txt文件,信息大约有200人。此信息每天生成和导出5或6次。每个txt文件平均每行800行。
我设置了一个cron,它调用(来自php命令行)一个执行此过程的codeigniter控制器:
我怎么能:
1-优化代码,这样我可以降低每个cron调用的2分钟(平均)执行时间?每个执行过程5/6 txt文件800avg。每行
2-设置MySQL表,以便它可以容纳非常大的qtty记录而不用麻烦?存储的字段是2:“code”int(2)和“fecha”时间戳,在唯一索引(代码,fecha)中设置
我有一台快速PC,表格设置为InnoDB
答案 0 :(得分:1)
您应该分析您的代码以确定瓶颈的位置。
您可以通过拆分IO和CPU任务来加快速度。除非你已经将文件保存到多个磁盘或这些行中的某些内容,否则让多个进程执行IO是没有意义的,所以专门用一个IO进程将文件读入内存并将它们放入队列中;然后你可以有多个CPU进程从队列中提取文件并处理它们。如果可能(例如,如果你有足够的RAM),将这个处理过的数据添加到内存中队列,当你的IO进程完成将所有文件读入内存后,你可以让它将处理后的数据写回磁盘;如果没有足够的RAM将文件+已处理的数据存储在内存中,则IO进程在读写之间交替。您应该运行足够的CPU进程来利用您的硬件线程,这可能是您在CPU上拥有的核心数量,或核心数量* 2,如果您的CPU和操作系统支持超线程 - 使用各种数字进行一些计时实验达到一个好数字的过程。
如果您对代码进行了分析并发现IO是问题所在,那么看看您是否可以执行某些操作,例如在首次生成时将文件保存为几个zip文件 - 这将减少您的数据量从磁盘读取并且还会使其更连续,代价是在解压缩数据时需要额外的CPU处理。
答案 1 :(得分:0)
第一种方法
你试过了吗?
$this->db->insert_batch('table', $data);
其中$ data是包含要插入的对象/信息的数组。我不知道该方法的内部(虽然查看代码应该不难)但我几乎可以肯定这个方法在单个事务中完成整个插入。
现在通过调用每行的插入来实现它的方式意味着打开一个套接字/连接,执行检查以及每个事务需要执行的所有操作。因此,在这些情况下执行批量插入是一种方法,并且CI中的该功能正是这样做的,这意味着它将生成将在同一事务上执行的单个插入命令。
如果其中一个插入失败,您甚至可以回滚它,这样生成这些文件的人就可以按摩或修复数据。
第二种方法
如果您知道这些文件具有特定格式,您可以轻松使用mysql中的LOAD DATA INFILE实用程序,它将比您自己编写的任何工具具有更好的性能。
它的美妙之处在于你可以用它来调用它:
$this->db->query($bulk_insert_command);
其中$ bulk_insert_command实际上是一个类似于:
的字符串LOAD DATA [LOW_PRIORITY | CONCURRENT] [LOCAL] INFILE 'file_name'
[REPLACE | IGNORE]
INTO TABLE tbl_name
[CHARACTER SET charset_name]
[{FIELDS | COLUMNS}
[TERMINATED BY 'string']
[[OPTIONALLY] ENCLOSED BY 'char']
[ESCAPED BY 'char']
]
[LINES
[STARTING BY 'string']
[TERMINATED BY 'string']
]
[IGNORE number {LINES | ROWS}]
[(col_name_or_user_var,...)]
[SET col_name = expr,...]
如上面提供的链接所示。当然,你有一个功能来清理这个字符串,并替换文件名和选项以及你需要的任何东西。
最后,确保您在CI应用上的database.php中设置的任何用户都具有文件角色权限:
GRANT FILE on *.* TO user@localhost IDENTIFIED BY 'password';
这样,CI应用程序在运行此类查询时不会生成错误。