为了账号安全,请及时绑定邮箱和手机立即绑定

带有数据库查询的循环在每个循环中都会变慢

带有数据库查询的循环在每个循环中都会变慢

PHP
慕哥9229398 2022-05-27 09:52:44
我正在努力使用生成学校和教师的 XLSX 文件的 PHP 脚本。目标是生成一个包含几张纸的文件,每张纸是一所学校。每张纸上都有教师信息(姓名、姓氏、身份证、职位)我有 2 个表:学校 (id,school_number,school_name,level) 教师 (id,school_number,name,last_name)我的 php 代码是这样的:$level = $_GET['level'];$Sql= "select * from schools where level = '".$level."' order by school_number";$Query = $PDO->prepare($Sql);if($Query->Execute()){while($Schools = $Query->fetch()){    $Sql = "select * from teachers where school_number = ".$Schools['school_number'];    $Query2 = $PDO->prepare($Sql);    if($Query2->Execute())  {        WHILE($Teachers = $Query2->fetch())     {            //GENERATE XLSX FILE WITH DATA        }    }}}这不是我的实际代码,仅用于演示,您可以大致了解它的作用,而不会太深入兔子洞。它将根据学校级别生成一个文件,例如一个用于小学,一个用于高中,以此类推。所以,我遇到的问题不一定是编程,代码适用于大多数级别。它制作文件并正确放置数据。但是,在处理某个级别(比如小学)时,学校比其他级别多得多(大约 400 所,是其他级别的 4 倍),while 循环变得太慢并且它不会生成输出文件.我尝试将最大执行时间设置为原始值的两到四倍,也是 ram。没有什么不同。一件奇怪的事情:我在第一个查询中添加了 LIMIT 300 并且它工作正常。创建的文件。即使在 LIMIT 350 时,它也能做到。当它超过这个数字时,它开始表现得很奇怪。有什么想法可以解决这个问题吗?
查看完整描述

2 回答

?
泛舟湖上清波郎朗

TA贡献1818条经验 获得超3个赞

与 Miken32 的建议相呼应,使用 aJOIN同时从两个表中获取数据,还使用ORDER BY school_number. 然后,当您遍历组合表时,请记住(在局部变量中)school_number您看到的最新内容,这样您就可以注意到值何时发生变化……当您从一所学校搬到另一所学校时。(如果你在“学校之间”做事,别忘了在循环结束后做最后一次......)

现在的查询将需要更长的时间来执行(当然,无论如何您都应该teachers通过...索引表school_number),但它只会执行一次,并且会一次性为您提供所需的所有答案。

而且,是的,在编写新查询时使用“准备好的语句”:level在这种情况下,只有一个参数。

不用说,如果您真的打算对“所有级别”执行此操作,只需忽略该测试,ORDER BY LEVEL, SCHOOL_NUMBER并注意两列值的变化。数据库会很乐意一次性为您提供所需的所有信息。


查看完整回答
反对 回复 2022-05-27
?
冉冉说

TA贡献1877条经验 获得超1个赞

准备好的语句有两个优点。首先,用户输入被转义以解决 SQL 注入的任何问题。其次,该语句可以准备一次但多次执行以减少开销。您正在避免这两个好处。


尝试这样的事情:


<?php

$level = $_GET['level'];

// we use a placeholder and pass the value to execute()

$sql = "SELECT school_number FROM schools WHERE level = ? ORDER BY school_number";

$stmt = $PDO->prepare($sql);

if($stmt->execute([$level])) {

    $schools = $stmt->fetchAll(\PDO::FETCH_ASSOC);


    $sql = "SELECT * FROM teachers WHERE school_number = ?";

    // note statement is prepared outside the loop

    $stmt2 = $PDO->prepare($sql);

    foreach($schools as $school) {

        if($stmt2->execute([$school["school_number"]])) {

            while ($teachers = $stmt2->fetch()) {

                //GENERATE XLSX FILE WITH DATA

            }

        }

    }

}

虽然你可能会用 aJOIN来代替:


<?php

$level = $_GET['level'];

$sql = "SELECT teachers.* FROM teachers LEFT JOIN schools USING (school_number) WHERE schools.level = ?";

$stmt = $PDO->prepare($sql);

if($stmt->execute([$level])) {

    while ($teachers = $stmt->fetch()) {

        //GENERATE XLSX FILE WITH DATA

    }

}


查看完整回答
反对 回复 2022-05-27
  • 2 回答
  • 0 关注
  • 221 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号