【问题标题】:DB Query inside a foreach loop is making my application slowforeach 循环中的数据库查询使我的应用程序变慢
【发布时间】:2020-03-06 16:27:03
【问题描述】:

下面的代码用于在一个页面中显示一个包含 15 个结果的表格。为此,我使用了两个不同的数据库,一个是 wordpress 数据库,另一个是我创建的个人数据库。

第一个 Query 用于从 wordpress 数据库中获取表值,但它没有获取用户名,因为 wordpress 仅将用户 ID 存储在该表中。我唯一拥有正确用户名的地方是我的第二个个人数据库。

为此,我使用了 foreach 循环来替换用户名的 ID。因此,在循环内部,有一个用于获取用户名的新查询。

我的问题是,每次加载页面时,我都会同时运行 16 个数据库查询,因此它会发出 16 个数据库请求,这让我的页面变慢。

public function index() {

    $posts = DB::connection('mysql2')
        ->table('wp_rocketsciencebrposts')
        ->select('ID', 'post_title', 'post_status', 'post_author', 'post_date')
        ->whereIn('post_status', ['publish', 'private'])
        ->where('post_type', 'post')
        ->orderBy('id', 'desc')
        ->paginate(15, ['*'], 'posts');

    $posts = compact('posts');

    foreach($posts['posts'] as &$value){

        //this DB Query is making my page slow, since it's inside this foreach loop, therefore, making 16 database requests
        $value->post_author = DB::connection('mysql')
            ->table('users')
            ->select('name')
            ->where('rsbwordpressid', $value->post_author)
            ->value('name');

    }

    return view('posts/posts', $posts);

}

我确信解决方案非常简单,但我无法提出如何将第二个数据库查询置于循环之外的策略,从而避免所有不必要的数据库请求。

请帮忙。

【问题讨论】:

  • 1) 通过 AJAX 填充表格,而不是源代码; 2) 缓存结果。
  • 抱歉,我是新手,这对我来说太过分了。我没有在我的项目中的任何其他地方使用 AJAX。我认为也许有一个解决方案,通过创建另一个循环并将值存储在一个数组中,使用它来只发出一个 DB 请求,但我真的不知道我该怎么做。
  • 附加信息请求。 RAM 大小、# 核心、MySQL 主机服务器上的任何 SSD 或 NVME 设备?在 pastebin.com 上发布并分享链接。从您的 SSH 登录根目录中,文本结果为:B) SHOW GLOBAL STATUS;至少 24 小时正常运行时间后 C) 显示全局变量; D) 显示完整的处理程序;用于服务器工作负载调整分析,以提供使您的设计可以接受的建议。

标签: php laravel


【解决方案1】:

所以你可能会在使用 Laravel 和 Wordpress 时遇到一些奇怪的事情。我可以从 Laravel POV 给你一些建议,告诉你如何让它变得更好。


雄辩的模型

如果您还没有,请制作两个模型(PostUser)并设置它们之间的关系。

用户.php

class User extends Model
{
    /**
     * The table associated with the model.
     *
     * @var string
     */
    protected $table = 'wp_rocketsciencebrposts';

    public function posts()
    {
        return $this->hasMany(Post::class, 'post_author', 'name');
    }
}

Post.php

class User extends Model
{
    /**
     * The table associated with the model.
     *
     * @var string
     */
    protected $table = 'users';

    public function user()
    {
        return $this->belongsTo(User::class, 'name', 'post_author');
    }
}

控制器

在你的控制器中,你现在应该可以做这样的事情了

$post = Post::with('user')
            ->whereIn('post_status', ['publish', 'private'])
            ->where('post_type', 'post')
            ->orderBy('id', 'desc')
            ->paginate(15, ['*'], 'posts');

现在$posts 中的每个Post 对象都应该加载一个->user 关系。

您现在可以去$post->user->name 检索帖子作者的姓名

【讨论】:

    【解决方案2】:

    您应该使用一个带有连接的查询:

    $posts = DB::connection('mysql2')
        ->table('wp_rocketsciencebrposts')
        ->join('users', 'users.rsbwordpressid', '=', 'wp_rocketsciencebrposts.post_author')
        ->select('ID', 'post_title', 'post_status', 'post_author', 'post_date', 'users.name')
        ->whereIn('post_status', ['publish', 'private'])
        ->where('post_type', 'post')
        ->orderBy('id', 'desc')
        ->paginate(15, ['*'], 'posts');
    

    【讨论】:

    • 嘿,这个解决方案不起作用,因为正如我所提到的,我正在使用来自不同数据库的两个表,所以我的代码出现“表”未找到错误。虽然,我认为使用 join 对我来说是一个解决方案。我发布了另一个问题,以便使用您提出的方法找到解决方案。你能抽出几分钟看看吗?谢谢! -> stackoverflow.com/questions/60578741/…
    【解决方案3】:

    这就是我期待看到的答案:

    public function index() {
    
        $posts = DB::connection('mysql2')
        ->table('wp_rocketsciencebrposts')
        ->select('ID', 'post_title', 'post_status', 'post_author', 'post_date')
        ->whereIn('post_status', ['publish', 'private'])
        ->where('post_type', 'post')
        ->orderBy('id', 'desc')
        ->paginate(15, ['*'], 'posts');
    
        $user_ids = $posts->pluck('post_author')->toArray();
    
        $users = DB::connection('mysql')
        ->table('users')
        ->whereIn('rsbwordpressid', $user_ids)
        ->pluck('rsbwordpressid', 'name')
        ->toArray();
    
        $posts = compact('posts');
    
        $users = array_flip($users);
    
        foreach($posts['posts'] as $value) {
    
            $value->post_author = $users[$value->post_author];
    
        }
    
        return view('posts/posts', $posts)->with('mensagemSucesso', print_r($users) );
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-04-19
      • 2018-07-05
      • 1970-01-01
      • 2020-06-25
      • 2017-09-23
      • 1970-01-01
      • 2015-06-14
      相关资源
      最近更新 更多