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

我正在努力使用生成学校和教师的 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 时,它也能做到。当它超过这个数字时,它开始表现得很奇怪。


有什么想法可以解决这个问题吗?


慕哥9229398
浏览 222回答 2
2回答

泛舟湖上清波郎朗

与 Miken32 的建议相呼应,使用 aJOIN同时从两个表中获取数据,还使用ORDER BY school_number. 然后,当您遍历组合表时,请记住(在局部变量中)school_number您看到的最新内容,这样您就可以注意到值何时发生变化……当您从一所学校搬到另一所学校时。(如果你在“学校之间”做事,别忘了在循环结束后做最后一次......)现在的查询将需要更长的时间来执行(当然,无论如何您都应该teachers通过...索引表school_number),但它只会执行一次,并且会一次性为您提供所需的所有答案。而且,是的,在编写新查询时使用“准备好的语句”:level在这种情况下,只有一个参数。不用说,如果您真的打算对“所有级别”执行此操作,只需忽略该测试,ORDER BY LEVEL, SCHOOL_NUMBER并注意两列值的变化。数据库会很乐意一次性为您提供所需的所有信息。

冉冉说

准备好的语句有两个优点。首先,用户输入被转义以解决 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])) {&nbsp; &nbsp; $schools = $stmt->fetchAll(\PDO::FETCH_ASSOC);&nbsp; &nbsp; $sql = "SELECT * FROM teachers WHERE school_number = ?";&nbsp; &nbsp; // note statement is prepared outside the loop&nbsp; &nbsp; $stmt2 = $PDO->prepare($sql);&nbsp; &nbsp; foreach($schools as $school) {&nbsp; &nbsp; &nbsp; &nbsp; if($stmt2->execute([$school["school_number"]])) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; while ($teachers = $stmt2->fetch()) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //GENERATE XLSX FILE WITH DATA&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}虽然你可能会用 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])) {&nbsp; &nbsp; while ($teachers = $stmt->fetch()) {&nbsp; &nbsp; &nbsp; &nbsp; //GENERATE XLSX FILE WITH DATA&nbsp; &nbsp; }}
打开App,查看更多内容
随时随地看视频慕课网APP