PHP:在不更改memory_limit和max_execution_time的情况下读取和导出大数据

时间:2018-10-22 09:50:05

标签: php memory bigdata

我有很多数据要导出到csv文件中。我的函数循环到每个字段并执行一个函数以从sql表获取数据。 现在我有一个非常大的数据库,我想导出一些数据而不更改memory_limit配置,因为我不想阻止其他用户。

我该如何执行我的功能?

例如: 我有10万人,每个人都有很多数据版本。他们每天都会保存这样的信息:

Person Table
+-----------+-------------+-------------+
| id_person | name_person | city_person |
+-----------+-------------+-------------+
| 1         | Jack        | Paris       |
+-----------+-------------+-------------+
| 2         | John        | London      |
+-----------+-------------+-------------+
| ...       | ...         | ...         |
+-----------+-------------+-------------+
| 99999     | Rose        | Madrid      |
+-----------+-------------+-------------+
| 100000    | Jackie      | Rome        |
+-----------+-------------+-------------+

Field Table
+----------+------------+-------------------+
| id_field | name_field | label_field       |
+----------+------------+-------------------+
| 1        | Location   | Visited location  |
+----------+------------+-------------------+
| 2        | Article    | Count of articles |
+----------+------------+-------------------+
| ...      | ...        | ...               |
+----------+------------+-------------------+
| 289      | Distance   | Distance          |
+----------+------------+-------------------+
| 299      | Pause      | Time of pause     |
+----------+------------+-------------------+

Field Value Table
+----------+----------+-----------+----------------+------------+
| id_value | id_field | id_person | value          | Date       |
+----------+----------+-----------+----------------+------------+
| 1        | 1        | 148       | Hanover Street | 2015-05-10 |
+----------+----------+-----------+----------------+------------+
| 2        | 66       | 57962     | 20             | 2015-05-10 |
+----------+----------+-----------+----------------+------------+
| ...      | ...      | ...       | ...            |            |
+----------+----------+-----------+----------------+------------+
| 3475992  | 105      | 847       | 17,5           | 2018-02-01 |
+----------+----------+-----------+----------------+------------+
| 3475993  | 15       | 66359     | 44             | 2018-02-01 |
+----------+----------+-----------+----------------+------------+

每个字段都有获取数据的特定功能。

如何在不更改限制内存的情况下获取所有要导出到csv文件中的数据?

谢谢

3 个答案:

答案 0 :(得分:0)

使用无缓冲查询,隐式刷新,将数据直接发送到输出缓冲区(用于下载),使用CLI(用于文件导出)。仅在此脚本(而不是全局)中关闭/增加时间限制(如果需要)。

http://php.net/manual/en/mysqlinfo.concepts.buffering.php

http://php.net/manual/en/wrappers.php.php

How to flush output after each `echo` call?(@ Roger的回答)

http://php.net/manual/en/function.set-time-limit.php

对于我来说,编写整个代码太多了,而且未知数太多。就像您使用的是什么数据库(MySQL,MsSQL等),什么是数据库类,PDO或MySqli?您是要导出到服务器上的文件还是要下载。您是否希望数据为CSV,SQL等。

  • 不缓冲查询将花费更多的网络资源,更长的时间,但将更好地管理内存并更好地处理更大的表。
  • 隐式刷新使输出缓冲区较小(管理内存)。
  • 将数据发送到php://output可以更好地进行内存管理,并且效率更高。
  • 时间限制应该很明显。
  

我的函数循环进入每个字段并执行一个函数以从sql表中获取数据。

使用联接而不是重复调用数据库,在表上使用适当的索引。

可以使用ini_set('memory_limit' ...)set_time_limit,因为它们仅影响当前的PHP进程,而不是全局的。显然,如果可能的话,最好避免使用它们,但是有时候那是不可能的。

最快的导出方式是mysqldump

https://dev.mysql.com/doc/refman/8.0/en/mysqldump.html

但是有局限性(例如)

https://dba.stackexchange.com/questions/4654/is-it-possible-to-mysqldump-a-subset-of-a-database-required-to-reproduce-a-query

您无法使用JOIN进行导出,并且复杂的查询将变得非常困难,因为我认为您只能使用基本的--where调用,而不能进行聚合等。

答案 1 :(得分:0)

有两种读取和导出大数据的方法

  • 通过批处理-将批量数据分成多个块并使用 sleep 然后继续处理下一块。
  • 将队列中的项目放入数据库

示例代码

(tag.value,tag)

答案 2 :(得分:-1)

尝试通过命令导出

mysqldump -p -u username database_name > dbname.csv