我目前正在运行此查询。但是,当在 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暂停。 另一个问题是我没有自己创建这个数据库,所以我没有自己设置索引。我正在考虑改进这些,因此我使用了解释命令:
我看到很多主键和几个双索引,但我不确定这是否会对性能产生如此大的影响。
编辑:这段代码占用了所有的执行时间:
$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
c
表 cluster
从不用于提取数据,仅用于 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/