简体   繁体   English

使用 Eloquent whereNotIn 时查询非常慢

[英]Very slow query when using Eloquent whereNotIn

I have a Question model from very large table of questions (600,000 records), with relation to Customer , Answer and Product models.我有一个Question model 来自非常大的问题表(600,000 条记录),与CustomerAnswerProduct模型有关。 Relations are irrelevant to this question but I mentioned them to clarify I need to use Eloquent.关系与这个问题无关,但我提到它们是为了澄清我需要使用 Eloquent。 When I call Question::with('customer')->get();当我打电话给Question::with('customer')->get(); it runs smoothly and fast.它运行平稳快速。

But there is another table in which I have question_id s of all questions which should not be shown (for specific reasons).但是还有另一个表,其中我有所有不应显示的question_id的 question_id (出于特定原因)。

I tried this code:我试过这段代码:

    // 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();

It takes so much time and shows this error: SQLSTATE[HY000]: General error: 1390 Prepared statement contains too many placeholders花了这么多时间并显示此错误: SQLSTATE[HY000]: General error: 1390 Prepared statement contains too many placeholders

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

When I run it with plain sql query:当我使用普通的 sql 查询运行它时:

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

it takes only 80 milliseconds仅需 80 毫秒

How can I use Eloquent in this situation?在这种情况下如何使用 Eloquent?

You can use whereRaw method: 您可以使用whereRaw方法:

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

But ideally as you found out this is a better sollution: 但是理想情况下,如您所见,这是一个更好的解决方案:

Question::with('customer')->whereNotIn('question_id', 
    function ($query) { 
        $query->from('question_to_product') ->select('question_id'); 
    }
);

Difference? 区别?

  1. When you will migrate your database to another database the whereRaw might not work as you put in raw statements. 当您将数据库迁移另一个数据库时whereRaw可能无法像您输入原始语句那样工作。 That is why we have Eloquent ORM which handles these transitions and build the appropriate queries to run. 这就是为什么我们有Eloquent ORM来处理这些转换并构建适当的查询以运行的原因。

  2. No performance impact because the SQL is the same (for MySQL ) 由于SQL是相同的,因此不会对性能造成影响(对于MySQL

PS: For better debugging try installing this debug bar PS:为获得更好的调试效果,请尝试安装此调试栏

refer from https://laravel.com/docs/5.4/queries#where-clauses 参考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();

It'll work 100%.它会 100% 工作。 When you query getting longer to response like more than 30 seconds when you are using whereNotIn.当您使用 whereNotIn 时,查询的响应时间会超过 30 秒。 Use this Query Syntax.使用此查询语法。

 $order = Order::on($databaseCredentials['database'])
->whereRaw('orders_id NOT IN (SELECT orders_id FROM orders)')
->skip($page)
->take(10)
->orderBy('orders.updated_at', 'ASC')
->paginate(10);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM