Laravel 优化求和查询
Laravel Optimise sum query
我想获得存款、取款和净额的总和。目前,我有 ~10,335,633 行数据(~1.8GB),计算总和需要超过 7 秒。我应该如何改进我的查询以使其更快?
查询:
$depositQuery = Deposit::whereBetween('created_at', [$start, $end])->approved();
$withdrawQuery = Withdraw::whereBetween('created_at', [$start, $end])->approved();
if ($request->has('user_id')) {
$depositQuery = $depositQuery->where('user_id', $request->user_id);
$withdrawQuery = $withdrawQuery->where('user_id', $request->user_id);
}
$deposits = $depositQuery->sum('amount');
$withdraws = ($withdrawQuery->sum('amount')) * -1;
$net = $deposits + $withdraws;
结果:
Deposit Withdraw Net Amount
20,946.00 15,066.00 5,880.00
基本上,laravel eloquent 与 sum()
的优化没有任何关系,它只是将您的代码转换为 SQL 查询。进入你的问题
Remeber: You can't optimize the sum function itself *(unless you are some real jedi)
你的数据库中有1M条记录,MySQLsum需要遍历所有记录才能计算出总和。在那种情况下,我认为 7 秒是可以的。根据这个问题here,一条7M的记录sum()
table 大约用了22秒。因此,根据您的架构、机器等...速度可能会有所不同。
那么如何才能继续改进响应时间呢?
在将记录交给 sum()
处理之前,您必须以某种方式减少记录数。
我想你可以做的一种方法是,你可以计算 10k 记录的总和 batches/chunks 并将其存储在单独的 table 中,并具有适当的日期和时间范围。这个的广义术语是 archiving。然后,当您必须计算给定日期范围内的总和时,请使用新 table 中的先前完整总和并使用它。您可以设置一个 chron 作业来更新这个 table 一天之内的一个或其他东西以确保数据始终正确。
另一种方法是partition MySQL tables。这似乎也是一种很有前途的方式。这也是一种归档。但我不是很有经验,无法对此发表任何评论。 Google 应该能帮到你。
像 created_at
这样的列上的索引以及您用于批准范围的列应该会缩短响应时间,但与利用归档技术相比不会有太大的改善。
此外,我有 MySQLmysql 查询缓存 来自上面指定的相同 link 的答案,more info.您可以尝试使用。但是从 mysql 8 开始,它已被弃用,而且,如果您有多个实例 运行 并且如果您已分区 tables,它将无法按预期工作。
我想获得存款、取款和净额的总和。目前,我有 ~10,335,633 行数据(~1.8GB),计算总和需要超过 7 秒。我应该如何改进我的查询以使其更快?
查询:
$depositQuery = Deposit::whereBetween('created_at', [$start, $end])->approved();
$withdrawQuery = Withdraw::whereBetween('created_at', [$start, $end])->approved();
if ($request->has('user_id')) {
$depositQuery = $depositQuery->where('user_id', $request->user_id);
$withdrawQuery = $withdrawQuery->where('user_id', $request->user_id);
}
$deposits = $depositQuery->sum('amount');
$withdraws = ($withdrawQuery->sum('amount')) * -1;
$net = $deposits + $withdraws;
结果:
Deposit Withdraw Net Amount
20,946.00 15,066.00 5,880.00
基本上,laravel eloquent 与 sum()
的优化没有任何关系,它只是将您的代码转换为 SQL 查询。进入你的问题
Remeber: You can't optimize the sum function itself *(unless you are some real jedi)
你的数据库中有1M条记录,MySQLsum需要遍历所有记录才能计算出总和。在那种情况下,我认为 7 秒是可以的。根据这个问题here,一条7M的记录sum()
table 大约用了22秒。因此,根据您的架构、机器等...速度可能会有所不同。
那么如何才能继续改进响应时间呢?
在将记录交给 sum()
处理之前,您必须以某种方式减少记录数。
我想你可以做的一种方法是,你可以计算 10k 记录的总和 batches/chunks 并将其存储在单独的 table 中,并具有适当的日期和时间范围。这个的广义术语是 archiving。然后,当您必须计算给定日期范围内的总和时,请使用新 table 中的先前完整总和并使用它。您可以设置一个 chron 作业来更新这个 table 一天之内的一个或其他东西以确保数据始终正确。
另一种方法是partition MySQL tables。这似乎也是一种很有前途的方式。这也是一种归档。但我不是很有经验,无法对此发表任何评论。 Google 应该能帮到你。
像 created_at
这样的列上的索引以及您用于批准范围的列应该会缩短响应时间,但与利用归档技术相比不会有太大的改善。
此外,我有 MySQLmysql 查询缓存 来自上面指定的相同 link 的答案,more info.您可以尝试使用。但是从 mysql 8 开始,它已被弃用,而且,如果您有多个实例 运行 并且如果您已分区 tables,它将无法按预期工作。