【问题标题】:Slow MySQL query in Laravel is fast elsewhereLaravel 中的慢 MySQL 查询在其他地方很快
【发布时间】:2015-07-04 22:49:12
【问题描述】:

我在 Laravel 4.2 应用程序中使用 Eloquent。我的一个控制器在大约 6000 毫秒后返回一个视图,这太长了。它处理来自名为responses 的表中的数据。几千行它工作得很好,但是当我超过 30000 时它开始变得非常慢。

这是奇怪的部分。 如果我检查我的DB::getQueryLog();,我可以看到这个查询:

[1] => Array
        (
            [query] => select * from `response` where `survey_id` = ? and `question_id` = ? and `resp_group` in (?, ?)
            [bindings] => Array
                (
                    [0] => 48
                    [1] => 25
                    [2] => a
                    [3] => b
                )

            [time] => 11
        )

我认为这会导致这个实际查询:

select * from `response` 
where `survey_id` = 48 
and `question_id` = 25 
and `resp_group` in ('a', 'b');

如您所见,那里的时间相当长。日志告诉我,我在 7 点到 11 点之间运行了大约 40 次这样的查询。

但如果我在 HediSQL 中运行相同的查询,我会在 PHPMyAdmin 中得到 0,000 秒和 0.0010 秒。我必须跑 20 次才能获得 0,015 秒。

解释一下:

    select_type: SIMPLE
    table: response
    possible_keys: 
      question_id_4, 
      resp_group_survey_id, 
      survey_id, 
      resp_group_question_id_survey_id
    key: question_id_4
    key_len: 8
    ref: const,const
    rows: 949
    Extra: Using where

所以有索引。为什么相同的查询在 Eloquent 执行时会这么慢,而当我直接在 MySQL 服务器上运行时却快得多?

(我在本地 WAMP 服务器上运行)

【问题讨论】:

    标签: php mysql database laravel eloquent


    【解决方案1】:

    DB::getQueryLog() 中的时间以毫秒为单位报告,因此与 PHPMyAdmin 报告的时间大致相同。

    控制器方法执行需要6秒的原因可能与Eloquent从数据库中获取数据后需要处理的数据量(30000行)有关。

    如果您想加快速度,请改用 DB 类。

    DB::table('response')
    ->whereSurveyId($survey_id)
    ->whereQuestionId($question_id)
    ->whereIn('resp_group', $groups)
    ->get();
    

    get() 提供所需列的列表也可能会有所帮助,这样您可以从数据库中获取更少的数据。

    【讨论】:

    • 我得到的行数不会影响速度。如果我得到 17000 行或 1000 行,则需要相同的时间。问题是它会随着表的增长而变慢——即使我已经索引了每一个可以想到的列组合。
    • 正如我上面写的,DB::getQueryLog() 所说的是查询需要 11 毫秒来执行,所以不是查询使控制器变慢。
    • 谢谢!像这样运行查询实际上将时间从 >6000 毫秒减少到大约 900 毫秒。为什么 DB 类要快得多?除非它只是一个实体,否则使用 E​​loquent 进行获取真的有任何意义吗?
    • Eloquent 对象使得对底层数据的操作变得非常容易,并且构建对象的开销很低,所以只要你不获取太多对象或不处理,它通常是一个更好的选择沉重的物体。当您获取大量数据时,将普通数据转换为对象所需的时间会增加,但增加更多开销的是 Eloquent 的魔法 getter 和 setter。每次执行“$model->attributeName”时,都会执行一系列方法,只是为了给您“attribute”的值。
    • 哦,我明白了。那么在访问属性时,使用 DB 对象可以减少很多开销吗?我很惊讶我基本上可以保持我雄辩的代码完整而只更改查询。
    猜你喜欢
    • 2013-07-16
    • 1970-01-01
    • 2021-01-04
    • 2011-06-27
    • 1970-01-01
    • 1970-01-01
    • 2022-01-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多