php - 如何提高查询性能(使用 explain 命令结果 f.e.)

标签 php mysql performance http-status-code-504

我目前正在运行此查询。但是,当在 phpMyAdmin 之外运行时,它会导致 504 超时错误。我认为这与查询返回或访问行数的效率有关。

我对 MySQL 不是很熟悉,所以这是我能做的最好的:

SELECT
                    s.surveyId,
                    q.cat,
                    SUM((sac.answer_id*q.weight))/SUM(q.weight) AS score,
                    user.division_id,
                    user.unit_id,
                    user.department_id,
                    user.team_id,
                    division.division_name,
                    unit.unit_name,
                    dpt.department_name,
                    team.team_name
                FROM survey_answers_cache sac
                    JOIN surveys s ON s.surveyId = sac.surveyid
                    JOIN subcluster sc ON s.subcluster_id = sc.subcluster_id
                    JOIN cluster c ON sc.cluster_id = c.cluster_id
                    JOIN user ON user.user_id = sac.user_id
                    JOIN questions q ON q.question_id = sac.question_id
                    JOIN division ON division.division_id = user.division_id
                    LEFT JOIN unit ON unit.unit_id = user.unit_id
                    LEFT JOIN department dpt ON dpt.department_id = user.department_id
                    LEFT JOIN team ON team.team_id = user.team_id
                WHERE c.cluster_id=? AND sc.subcluster_id=? AND s.active=0 AND s.prepare=0
                GROUP BY user.team_id, s.surveyId, q.cat
                ORDER BY s.surveyId, user.team_id, q.cat ASC

我在这个查询中遇到的问题是,当我得到返回的正确结果时,它运行得很快(比方说 +-500 毫秒),但是当结果有两倍多的行时,它需要超过 5 分钟,然后导致 504暂停。 另一个问题是我没有自己创建这个数据库,所以我没有自己设置索引。我正在考虑改进这些,因此我使用了解释命令:


Explain command result


我看到很多主键和几个双索引,但我不确定这是否会对性能产生如此大的影响。

编辑:这段代码占用了所有的执行时间:

$start_time = microtime(true);
$stmt = $conn->query($query); //query is simply the query above.
while ($row = $stmt->fetch_assoc()){
    $resultSurveys["scores"][] = $row;
}
$stmt->close();
$end_time = microtime(true);
$duration = $end_time - $start_time; //value typically the execution time #reallyHigh...

所以我的问题:是否可以(极大地?)通过更改数据库键来提高查询的性能,或者我应该将我的查询分成多个较小的查询?

最佳答案

你可以尝试这样的事情(虽然这对我来说不切实际)

SELECT
    sac.surveyId,
    q.cat,
    SUM((sac.answer_id*q.weight))/SUM(q.weight) AS score,
    user.division_id,
    user.unit_id,
    user.department_id,
    user.team_id,
    division.division_name,
    unit.unit_name,
    dpt.department_name,
    team.team_name
FROM survey_answers_cache sac
    JOIN
    (
        SELECT
            s.surveyId,
            sc.subcluster_id
        FROM
            surveys s
            JOIN subcluster sc ON s.subcluster_id = sc.subcluster_id
            JOIN cluster c ON sc.cluster_id = c.cluster_id
        WHERE
            c.cluster_id=? AND sc.subcluster_id=? AND s.active=0 AND s.prepare=0
    ) AS v ON v.surveyid = sac.surveyid
    JOIN user ON user.user_id = sac.user_id
    JOIN questions q ON q.question_id = sac.question_id
    JOIN division ON division.division_id = user.division_id
    LEFT JOIN unit ON unit.unit_id = user.unit_id
    LEFT JOIN department dpt ON dpt.department_id = user.department_id
    LEFT JOIN team ON team.team_id = user.team_id
GROUP BY user.team_id, v.surveyId, q.cat
ORDER BY v.surveyId, user.team_id, q.cat ASC

所以我希望我没有搞砸任何事情。

无论如何,想法是在内部查询中,您根据 where 条件仅选择所需的行。这将创建一个较小的 tmp 表,因为它只提取 2 个字段,都是整数。

然后在外部查询中,您连接到实际从中提取其余数据、排序和分组的表。这样您就可以在较小的数据集上进行排序和分组。并且您的 where 子句可以以最佳方式运行。

您甚至可以省略其中一些表,因为您只是从其中的一些表中提取数据,但没有看到完整的模式以及它如何相关,这很难说。

不过一般来说这部分(子查询)

SELECT
    s.surveyId,
    sc.subcluster_id
FROM
    surveys s
    JOIN subcluster sc ON s.subcluster_id = sc.subcluster_id
    JOIN cluster c ON sc.cluster_id = c.cluster_id
WHERE
    c.cluster_id=? AND sc.subcluster_id=? AND s.active=0 AND s.prepare=0

是什么直接受您的 WHERE 子句影响。看吧,我们可以优化这部分,然后用它来加入您需要的其余数据。

从上面可以很容易地推导出一个删除表的例子,考虑一下

SELECT
    s.surveyId,
    sc.subcluster_id
FROM
    surveys s
    JOIN subcluster sc ON s.subcluster_id = sc.subcluster_id
WHERE
    sc.cluster_id=? AND sc.subcluster_id=? AND s.active=0 AND s.prepare=0

ccluster 从不用于提取数据,仅用于 where。所以不是

    JOIN cluster c ON sc.cluster_id = c.cluster_id
 WHERE
    c.cluster_id=?

相同或等同于

WHERE
    sc.cluster_id=?

因此我们可以完全消除该连接。

关于php - 如何提高查询性能(使用 explain 命令结果 f.e.),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48453438/

相关文章:

mysql - 在 MySQL 中,为什么我必须定义外键关系?

c# - SQL 查询错误

Python交换一个数字中的两位数?

php - mysql_fetch_array()/mysql_fetch_assoc()/mysql_fetch_row()/mysql_num_rows 等...期望参数 1 是资源

php - 输出函数 mysql php

php - Google chrome 版本 84.0.4147.125(官方构建)(64 位)在重定向来自第三方的回调函数时破坏应用程序 session

php - 如何将 4 个单选按钮(每种颜色 4 种)存储到我的数据库中?

mysql - 我怎样才能使这个 mysql 查询更有效并运行得更快?

ios - 以快速、缓慢的性能和低 FPS 绘制应用程序

javascript - 如何创建您自己的基本 WordPress 小部件