Laravel 查询生成器 orderBy id DESC 在 100k 行上非常慢

Laravel Query Builder orderBy id DESC is very slow on 100k rows

我有一个包含 10 万个产品的数据库,这是我的查询

 $products = DB::table('product')
    ->leftJoin('product_description', 'product_description.product_id', 'product.product_id')
    ->leftJoin('product_to_category','product_to_category.product_id','product.product_id')
    ->select(self::$select_fields)
    ->where('product_description.language', $language)
    ->groupBy('product.product_id');

    if (!empty($filter->keyword)) {
      $products->where('product_description.title','LIKE','%'. $filter->keyword .'%');
    }

    if (!empty($filter->category_id)) {
      $products->where('product_to_category.category_id','=',$filter->category_id);
    }
    
    if (!empty($filter->range)) {
      $range= explode(',',$filter->range);
      $products->whereBetween('product.price', [$range[0], (!empty($range[1]))? $range[1] : $range[0]]);
    }
    
    return $products->orderBy('product.product_id','DESC')->where('product.status',1)->limit(50);

此查询加载时间为 12.6 秒。如果我删除 ->orderBy('product.product_id','DESC'),查询将在 0.800 毫秒内运行。

在我的数据库中,我在 product_description.product_idproduct_to_category.product_id 上有索引键product.id 设置为主

我已经看到 orderBY desc 在大型数据库中速度变慢了很多,有没有解决方法,我需要按 DESC 订购它,因为我想上传“最新”,我试过将它设置为“created_at”列,但大致相同

编辑

我在没有Laravel的情况下尝试过,基本上速度差不多,按DESC排序会减慢查询速度,一般有解决办法还是基本上DESC很慢,应该避免使用大型数据库?

您按 product.product_id 分组,我 猜测 select 仅包含来自产品 table。在那种情况下,左连接可以被删除——或者——被一个存在的查询替换。 group by 可以完全删除。联接乘以行并按压缩它们进行分组;删除后查询变得更简单,希望更快:

select foo, bar, baz
from product
where status = ?
and price between ? and ? -- add this where clause if you need to filter on product price
and exists ( -- add this subquery if you need to filter on description language and/or title
    select 1
    from product_description
    where product_description.product_id = product.product_id
    and product_description.language = ?
    and product_description.title like ?
)
and exists ( -- add this subquery if you need to filter on category id
    select 1
    from product_to_category
    where product_to_category.product_id = product.product_id
    and product_to_category.category_id = ?
)
order by product_id desc
limit 50

我想你可以定义 DESC 索引,因为列的默认索引是 ASC

例如:

CREATE INDEX product_index ON product (product_id DESC);

more information