【发布时间】:2021-01-26 20:40:59
【问题描述】:
我使用Laravel 8 直接使用query builder 对MySQL 8 表执行查询以避免Eloquent 开销,但无论如何我都会消耗大量内存。
为了向您展示一个示例,我执行以下查询以准确选择 300 000 个元素。
我的代码如下所示:
$before = memory_get_usage();
$q_coords = DB::table('coords')->selectRaw('alt, lat, lng, id')
->where('active', 1)->take(300000)->get();
$after = memory_get_usage();
echo ($after - $before);
如果我没记错的话,它会显示 169760384 这意味着类似于 169MB..
对我来说看起来很多,因为在我的查询中,我只要求 2 float 和 2 bigInt,它们代表 4 x 8 字节(32 字节强>)。
而且.. 32 x 300 000 条记录 ~= 9600000(几乎 10MB)。
它怎么可能使用这么多内存?我很惊讶。
编辑
我也试过直接使用PDO,结果一样。
$query = DB::connection()->getPdo()->query("select alt, lat, lng, id from coords WHERE active = 1 LIMIT 300000");
$q_coords = $query->fetchAll();
【问题讨论】:
-
你的问题到底是什么?原因 300 000 个条目对于任何代码都不是正常行为。 + 在 php 中,每个变量都被构造为一个 zend 对象 + 每个 Eloquent 的结果都被转换为一个 PHP 对象...
-
@N69S 我没有使用
Eloquent来避免Models造成的开销,而是使用stdClass。我得到 300k 条目以稍后执行一些计算,但在这里我只是想了解为什么它确实使用那么多内存来进行个人理解,而我期望它使用更少(因为我知道我可以使用chunks或cursors无论如何)。处理 32 字节的记录似乎有很多“周围”的东西.. -
如果你真的需要在单个查询中访问300.000条记录,那么尝试直接使用pdo并使用
PDO::FETCH_NUM。 -
get()->toArray()怎么样? -
@Marc 所以这个
->where('active', 1)->take(300000)->get()不是很有说服力吗?
标签: php mysql laravel laravel-query-builder