我在一个最大的应用程序(超过100万用户)中工作,我试图获得每个用户在记分板部分的排名,但有一个问题:结果非常慢
这是我的数据库的体系结构:
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
...
});
Schema::create('topics', function (Blueprint $table) {
$table->increments('id');
...
});
主题表有20多行
Schema::create('user_scores', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->integer('topic_id')->unsigned();
$table->unique(['user_id', 'topic_id']);
$table->float('timer');
$table->integer('score');
});
对用户进行排名的查询
User::where('type',0)->get()->each(function ($user) {
$user->topics= $user->scores->sum('score');
$user->timing= $user->scores->sum('timer');
})->sort(function ($a, $b){
return ($b->topics - $a->topics) == 0
? ($a->timing - $b->timing)
: ($b->topics - $a->topics);
})->values()->each(function($user, $key){
$user->rank = $key +1;
});
任何优化我应该使得到的结果更快?谢谢。
1条答案
按热度按时间c3frrgcw1#
你一打电话
get()
,all()
,find()
或者first()
在查询生成器上,您将要求雄辩的引擎执行查询并返回结果。所以在您的例子中,所有的排序和分组都是在内存中执行的,这会带来非常糟糕的性能。您可以做的是改进您的查询:
对于行号(或排名,或您想怎么称呼它),您可能希望搜索现有的问题和答案。老实说,回答这个问题对这个答案来说太过分了。显然,您不应该使用这种方法,因为它还会计算内存中的行号。
但显然,如何处理查询结果也很重要。你正在向用户显示一百万行吗?如果是这样的话,最终的瓶颈肯定是浏览器。您可能需要考虑使用分页
paginate()
而不是get()
.