执行两个 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次?