执行两个 mysql 查询变得非常慢
Execution of two mysql queries gets extremely slow
我制作了一个 php-脚本,它完全符合我的要求,但它在服务器上速度极慢。当我在本地测试时,运行整个脚本的时间约为 60-80 毫秒。当我在我的网络服务器上 运行 它需要大约 4 秒。但是我不清楚网络服务器上的问题是什么。
在注释掉脚本的soms 部分时,我可以将问题定位到while 循环中的第二个查询。当我不执行第二个查询时,执行时间又回到了 60 毫秒左右。但最奇怪的是,while 循环仅限于 8 个结果,并且查询示例在网络服务器上的 phpmyadmin 中给出了不到 1 毫秒的执行时间。所以我很困惑 60ms + 8* 1 ms 总共可以达到 4 秒。所以我认为一定有其他东西在减慢脚本的速度,但我不清楚那是什么。我希望有人能给我一个线索,在哪里看。
查询 1 的第一部分(最多 8 个结果):
$sql = "
SELECT W.*
, P.weektaak
, P.extra
, P.toets
, P.toets2
, P.toetsdag
, P.toetsdag2
, P.toetssoort
FROM weken W
LEFT
JOIN planner P
ON P.weekid = W.id
AND P.vakid = ?
AND P.studieid = ?
WHERE W.id >= ?
ORDER
BY W.id
LIMIT 8";
$stmt = $mysqli->prepare($sql);
$stmt->bind_param('sss', $checkrow['vakid'], $checkrow['studieid'], $_SESSION['weekid']);
$stmt->execute();
$res = $stmt->get_result();
$stmt->close();
if ($res->num_rows >= 1) {
while ($row = $res->fetch_assoc()) {
查询 2 的第二部分(最多重复 8 次):
$toetssql = "SELECT S.leerjaar, S.studie, V.afkorting, P.toets, P.toets2, P.toetsdag, P.toetsdag2, P.toetssoort FROM vakkenkoppeling K
LEFT JOIN planner P ON P.studieid = K.studieid AND P.vakid = K.vakid AND P.weekid = ?
LEFT JOIN studie S ON K.studieid = S.id
LEFT JOIN vakken V ON K.vakid = V.id
WHERE S.leerjaar = ? AND S.studie = ? AND (P.toets != '' OR P.toets2 != '')
ORDER BY P.toetsdag";
$stmt2 = $mysqli->prepare($toetssql);
$stmt2->bind_param('sss', $row['id'], $checkrow['leerjaar'], $checkrow['studie']);
$stmt2->execute();
$toetsres = $stmt2->get_result();
$stmt2->close();
if ($toetsres->num_rows >= 1) {
while ($toetsrow = $toetsres->fetch_assoc()) {
我已经读到建议将查询留在循环之外,但我无法想象如何在此脚本中做到这一点。除此之外,我以前在循环中使用过查询,但从未经历过这种缓慢。
提前感谢任何可以帮助我的线索。
--- 编辑 07/19
我认为这两种反应已经将我推向了解决这个问题的正确方向。所以我现在要研究索引,但我会先 post EXPLAIN 的结果:
查询 1
id select_type table type possible_keys key key_len ref row Extra
1 SIMPLE W range PRIMARY PRIMARY 4 NULL 53 Using index condition
1 SIMPLE P ALL NULL NULL NULL NULL 6421 Using where
查询 2
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE K ALL NULL NULL NULL NULL 233 Using temporary; Using filesort
1 SIMPLE S eq_ref PRIMARY PRIMARY 4 plannersagnieten_planner.K.studieid 1 Using where
1 SIMPLE V eq_ref PRIMARY PRIMARY 4 plannersagnieten_planner.K.vakid 1
1 SIMPLE P ALL NULL NULL NULL NULL 6421 Using where```
LEFT JOIN planner P ON P.weekid = W.id
AND P.vakid = ?
AND P.studieid = ?
和
LEFT JOIN planner P ON P.studieid = K.studieid
AND P.vakid = K.vakid
AND P.weekid = ?
两者都需要 INDEX(weekid, valid, studieid)
(顺序不限)
LEFT JOIN studie S ON K.studieid = S.id
LEFT JOIN vakken V ON K.vakid = V.id
WHERE S.leerjaar = ?
AND S.studie = ?
不是“LEFT”联接,因为您指定了 2 列的值。我建议添加 INDEX(leerjaar, studie, id)
AND (P.toets != '' OR P.toets2 != '' )
一般来说,OR
无法优化。但请提供 EXPLAIN
.
ORDER BY P.toetsdag
可能受益于 INDEX(toetsdag)
为什么要运行查询8次?
我制作了一个 php-脚本,它完全符合我的要求,但它在服务器上速度极慢。当我在本地测试时,运行整个脚本的时间约为 60-80 毫秒。当我在我的网络服务器上 运行 它需要大约 4 秒。但是我不清楚网络服务器上的问题是什么。
在注释掉脚本的soms 部分时,我可以将问题定位到while 循环中的第二个查询。当我不执行第二个查询时,执行时间又回到了 60 毫秒左右。但最奇怪的是,while 循环仅限于 8 个结果,并且查询示例在网络服务器上的 phpmyadmin 中给出了不到 1 毫秒的执行时间。所以我很困惑 60ms + 8* 1 ms 总共可以达到 4 秒。所以我认为一定有其他东西在减慢脚本的速度,但我不清楚那是什么。我希望有人能给我一个线索,在哪里看。
查询 1 的第一部分(最多 8 个结果):
$sql = "
SELECT W.*
, P.weektaak
, P.extra
, P.toets
, P.toets2
, P.toetsdag
, P.toetsdag2
, P.toetssoort
FROM weken W
LEFT
JOIN planner P
ON P.weekid = W.id
AND P.vakid = ?
AND P.studieid = ?
WHERE W.id >= ?
ORDER
BY W.id
LIMIT 8";
$stmt = $mysqli->prepare($sql);
$stmt->bind_param('sss', $checkrow['vakid'], $checkrow['studieid'], $_SESSION['weekid']);
$stmt->execute();
$res = $stmt->get_result();
$stmt->close();
if ($res->num_rows >= 1) {
while ($row = $res->fetch_assoc()) {
查询 2 的第二部分(最多重复 8 次):
$toetssql = "SELECT S.leerjaar, S.studie, V.afkorting, P.toets, P.toets2, P.toetsdag, P.toetsdag2, P.toetssoort FROM vakkenkoppeling K
LEFT JOIN planner P ON P.studieid = K.studieid AND P.vakid = K.vakid AND P.weekid = ?
LEFT JOIN studie S ON K.studieid = S.id
LEFT JOIN vakken V ON K.vakid = V.id
WHERE S.leerjaar = ? AND S.studie = ? AND (P.toets != '' OR P.toets2 != '')
ORDER BY P.toetsdag";
$stmt2 = $mysqli->prepare($toetssql);
$stmt2->bind_param('sss', $row['id'], $checkrow['leerjaar'], $checkrow['studie']);
$stmt2->execute();
$toetsres = $stmt2->get_result();
$stmt2->close();
if ($toetsres->num_rows >= 1) {
while ($toetsrow = $toetsres->fetch_assoc()) {
我已经读到建议将查询留在循环之外,但我无法想象如何在此脚本中做到这一点。除此之外,我以前在循环中使用过查询,但从未经历过这种缓慢。
提前感谢任何可以帮助我的线索。
--- 编辑 07/19
我认为这两种反应已经将我推向了解决这个问题的正确方向。所以我现在要研究索引,但我会先 post EXPLAIN 的结果:
查询 1
id select_type table type possible_keys key key_len ref row Extra
1 SIMPLE W range PRIMARY PRIMARY 4 NULL 53 Using index condition
1 SIMPLE P ALL NULL NULL NULL NULL 6421 Using where
查询 2
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE K ALL NULL NULL NULL NULL 233 Using temporary; Using filesort
1 SIMPLE S eq_ref PRIMARY PRIMARY 4 plannersagnieten_planner.K.studieid 1 Using where
1 SIMPLE V eq_ref PRIMARY PRIMARY 4 plannersagnieten_planner.K.vakid 1
1 SIMPLE P ALL NULL NULL NULL NULL 6421 Using where```
LEFT JOIN planner P ON P.weekid = W.id
AND P.vakid = ?
AND P.studieid = ?
和
LEFT JOIN planner P ON P.studieid = K.studieid
AND P.vakid = K.vakid
AND P.weekid = ?
两者都需要 INDEX(weekid, valid, studieid)
(顺序不限)
LEFT JOIN studie S ON K.studieid = S.id
LEFT JOIN vakken V ON K.vakid = V.id
WHERE S.leerjaar = ?
AND S.studie = ?
不是“LEFT”联接,因为您指定了 2 列的值。我建议添加 INDEX(leerjaar, studie, id)
AND (P.toets != '' OR P.toets2 != '' )
一般来说,OR
无法优化。但请提供 EXPLAIN
.
ORDER BY P.toetsdag
可能受益于 INDEX(toetsdag)
为什么要运行查询8次?