使用 Laravel 4.2 通过分页提高多对多查询性能

时间:2021-06-26 15:01:47

标签: mysql laravel performance eloquent laravel-4.2

我有一个看起来很简单的带有分页的多对多关系查询。它工作正常,但缺点是需要时间。在生产服务器上,超过 20 秒。在我的开发环境中,13 秒。

代码如下:

$query = $this->excerpt->orderBy($sort, $order);
$excerpts = $query->with('source.authors')
            ->with('excerptType')
            ->with('tags')
            ->whereHas('tags', function($q) use ($tagId){
                $q->where('tag_id', $tagId);
            })
            ->paginate($this->paginateCount);

这两个查询耗时最长

select count(*) as aggregate
    from `excerpt`
    where (select count(*)
            from `tags`
            inner join `excerpt_tag`
                  on `tags`.`id` = `excerpt_tag`.`tag_id`
            where `excerpt_tag`.`excerpt_id` = `excerpt`.`id`
                 and `tag_id` = '655') >= 1

2.02 秒

select *
    from `excerpt`
    where (select count(*) from `tags`
            inner join `excerpt_tag`
                    on `tags`.`id` = `excerpt_tag`.`tag_id`
            where `excerpt_tag`.`excerpt_id` = `excerpt`.`id`
              and `tag_id` = '655') >= 1
    order by `created_at` desc limit 15 offset 0

2.02 秒

我正在考虑将其更改为具有内部联接的简单查询,例如:

select *
    from `excerpt`
    inner join excerpt_tag  on excerpt.id = excerpt_tag.excerpt_id
    inner join tags  on excerpt_tag.tag_id = tags.id
    where tags.id = 655
    limit 10  offset 0

但是我失去了急切加载等的优势。

有人知道加快速度的最佳方法是什么吗?

1 个答案:

答案 0 :(得分:0)

改变

( SELECT COUNT(*) ... ) > 0

EXISTS ( SELECT 1 ... )

按照说明 here 获取 many:many 表中的索引提示。

如果 tag 只是一个短字符串,请不要为它们提供表格 (tags)。相反,只需将 tag 放在 excerpt_tag 中并去掉 tag_id

没有 LIMITORDER BY 有点没有意义——你得到的 10 行是不可预测的。