使用 Laravel 将数据库导出到 JSON 超出了内存限制
Exporting database to JSON using Laravel exceeds memory limit
我有一个 Laravel 应用程序,其底层数据库具有长序列。我想为用户提供以 JSON 格式下载数据库的机会。为此,我首先获取记录,然后将它们转换为 JSON 格式并写入文件。
但是,当我将应用程序移动到生产服务器时,它给了我
You don't have permission to access /saveJson on this server.
来自日志的错误消息是:
[2021-01-07 19:08:50] local.ERROR: Allowed memory size of 1887436800 bytes exhausted (tried to allocate 675803754 bytes) {"userId":1,"exception":"[object] (Symfony\Component\Debug\Exception\FatalErrorException(code: 1): Allowed memory size of 1887436800 bytes exhausted (tried to allocate 675803754 bytes) at /home/xxx/vendor/league/flysystem/src/Util/MimeType.php:205)
[stacktrace]
服务器中的memory_limit已经设置为-1,设置后重启
代码的相关部分:
DB::connection()->disableQueryLog();
$large_db = Model::with('regions', 'genes.gene_models.aro_categories')
->where('curated', '<>', 4)
->get();
$db_JSON = $large_db->toJSON();
Storage::disk('public')->put("database_$date.json", $db_JSON);
DB::connection()->enableQueryLog();
根据MySQL,整个数据库大约170M,根据meminfo,服务器有1962MB内存,所以我不完全理解为什么它不能加载记录——虽然因为数据库会被更新,我希望以一种将来不会因类似原因崩溃的方式创建它。
有没有更聪明的方法可以在不超过内存限制的情况下导出数据库?某种缓冲?
感谢您的任何建议!
toJSON()
将模型转换为数组,然后使用 PHP 的原生 json_encode()
将数据转换为 json。 Laravel Docs.
给出了使用 json_encode()
和 json_decode()
在 PHP 数组和 JSON 之间移动的内存效率估计。在回答者的计算中,PHP 数组消耗的内存大约是 JSON 序列化数据的 9 倍。
对这个问题采取天真的方法,我们可以假设我们需要大约 10 倍于生成的 JSON 文件大小的内存来将数据转储到文件中(如果我们'重新通过 PHP 数组)。
170MiB x 10 非常接近您的内存限制。包括 Laravel 对象中的额外内存开销,您正在耗尽所有可用内存是有道理的。
最好的选择是提出某种选项来转储数据库,从而跳过将其加载到 PHP 对象中。我建议编写一个 MySQL 查询,将 JSON 直接写入文件,然后返回生成的 JSON 文件。
我有一个 Laravel 应用程序,其底层数据库具有长序列。我想为用户提供以 JSON 格式下载数据库的机会。为此,我首先获取记录,然后将它们转换为 JSON 格式并写入文件。 但是,当我将应用程序移动到生产服务器时,它给了我
You don't have permission to access /saveJson on this server.
来自日志的错误消息是:
[2021-01-07 19:08:50] local.ERROR: Allowed memory size of 1887436800 bytes exhausted (tried to allocate 675803754 bytes) {"userId":1,"exception":"[object] (Symfony\Component\Debug\Exception\FatalErrorException(code: 1): Allowed memory size of 1887436800 bytes exhausted (tried to allocate 675803754 bytes) at /home/xxx/vendor/league/flysystem/src/Util/MimeType.php:205)
[stacktrace]
服务器中的memory_limit已经设置为-1,设置后重启
代码的相关部分:
DB::connection()->disableQueryLog();
$large_db = Model::with('regions', 'genes.gene_models.aro_categories')
->where('curated', '<>', 4)
->get();
$db_JSON = $large_db->toJSON();
Storage::disk('public')->put("database_$date.json", $db_JSON);
DB::connection()->enableQueryLog();
根据MySQL,整个数据库大约170M,根据meminfo,服务器有1962MB内存,所以我不完全理解为什么它不能加载记录——虽然因为数据库会被更新,我希望以一种将来不会因类似原因崩溃的方式创建它。
有没有更聪明的方法可以在不超过内存限制的情况下导出数据库?某种缓冲?
感谢您的任何建议!
toJSON()
将模型转换为数组,然后使用 PHP 的原生 json_encode()
将数据转换为 json。 Laravel Docs.
json_encode()
和 json_decode()
在 PHP 数组和 JSON 之间移动的内存效率估计。在回答者的计算中,PHP 数组消耗的内存大约是 JSON 序列化数据的 9 倍。
对这个问题采取天真的方法,我们可以假设我们需要大约 10 倍于生成的 JSON 文件大小的内存来将数据转储到文件中(如果我们'重新通过 PHP 数组)。
170MiB x 10 非常接近您的内存限制。包括 Laravel 对象中的额外内存开销,您正在耗尽所有可用内存是有道理的。
最好的选择是提出某种选项来转储数据库,从而跳过将其加载到 PHP 对象中。我建议编写一个 MySQL 查询,将 JSON 直接写入文件,然后返回生成的 JSON 文件。