使用Eloquent whereNotIn时查询速度非常慢

时间:2017-08-08 14:14:42

标签: mysql laravel eloquent

我从非常大的问题表(600,000条记录)中得到Question模型,与CustomerAnswerProduct模型有关。关系与这个问题无关,但我提到他们澄清我需要使用Eloquent。当我致电Question::with('customer')->get();时,它会平稳而快速地运行。

但还有另一张表格,其中question_id所有问题都不应该显示(出于特定原因)。

我试过这段代码:

    // omitted product ids, about 95,000 records
    $question_ids_in_product = DB::table('question_to_product')
                  ->pluck('product_id')->all();
    $questions =  Question::with('customer')
                  ->whereNotIn('product_id', $question_ids_in_product)
                  ->paginate($perPage)->get();

需要花费很多时间并显示此错误: SQLSTATE[HY000]: General error: 1390 Prepared statement contains too many placeholders

有时Fatal error: Maximum execution time of 30 seconds exceeded

当我使用普通的sql查询运行它时:

SELECT * FROM questions LEFT JOIN customers USING (customer_id) WHERE question_id NOT IN (SELECT question_id FROM question_to_product)

它只需要80毫秒

在这种情况下如何使用Eloquent?

2 个答案:

答案 0 :(得分:2)

您可以使用whereRaw方法:

/* 1 */
{
    "_id" : {
        "client" : "symphony"
    },
    "clientIdCount" : 4,
    "numberOfUsers" : 3
}

/* 2 */
{
    "_id" : {
        "client" : "merlin"
    },
    "clientIdCount" : 3,
    "numberOfUsers" : 2
}

但理想情况下,您发现这是一种更好的解决方案:

$questions =  Question::with('customer')
              ->whereRaw('question_id NOT IN (SELECT question_id FROM question_to_product)')
              ->paginate($perPage)->get();

差异?

  1. 当您迁移您的数据库另一个数据库时,Question::with('customer')->whereNotIn('question_id', function ($query) { $query->from('question_to_product') ->select('question_id'); } ); 可能无法正常放入原始语句。 这就是为什么我们有Eloquent ORM来处理这些转换并构建适当的查询来运行。

  2. 没有性能影响,因为SQL是相同的(对于whereRaw

  3. P.S:为了更好的调试,请尝试安装this debug bar

答案 1 :(得分:0)

参考https://laravel.com/docs/5.4/queries#where-clauses

$users = DB::table('questions')
            ->leftJoin('customers', 'curtomer.id', '=', 'question.user_id')
            ->whereNotIn('question_id', [1, 2, 3])
            ->get();