函数渲染使网站速度变慢 500%! 任何人都可以解决这个问题吗?



函数渲染使网站速度变慢500%!任何人都可以解决这个问题吗? 有人告诉我:

因为它在循环的每次迭代时都会发送一个数据库请求(这不是这段代码的唯一问题,但它是最费力的问题(

是的,我明白这意味着什么。他的方式是:

在开始构建菜单之前,您需要获取所有数据, 然后,您只需插入数据,而不是在每个数据上请求更多数据 迭 代

但我不知道我该怎么做!

<?php
$menu_html='';
function render_menu($parent_id,$actmenuid)
{
$obj = new Database(); 
$con = $obj->dbconnectt();
global $menu_html;
$result=mysqli_query($con, "select * from tbl_menu where parent_id='$parent_id'");

if(mysqli_num_rows($result)==0) return;
if($parent_id==0){
$menu_html.='<ul class="topnav">';
}else{
$menu_html.='<ul>';
}
while($row=mysqli_fetch_array($result)) {
$childnum = $obj->recordcount("SELECT * FROM tbl_menu WHERE parent_id='".$row['id']."'");
if($childnum == 0){ 
$linkvalue='/category/'.$row['id'].'.html';
} else{ 
$linkvalue='#';
}

if($row['id']==$actmenuid && $actmenuid !=NULL){
$actv='class="active"';
}else{
$actv='';
}

$menu_html.='<li '.$actv.'><a href="'.$linkvalue.'">'.$row['title'].'</a>';
render_menu($row['id'],$actmenuid);
$menu_html.='</li>';
}
$menu_html.='</ul>';return $menu_html;
}
if($isDsh==false){
echo render_menu(0,$actmenuid);
}
?>

根据您拥有的记录数,请尝试从循环中删除此查询,因为它针对第一个查询的每个记录运行。

$childnum = $obj->recordcount("SELECT * FROM tbl_menu WHERE parent_id='".$row['id']."'");

像这样将其更改为单个查询,其中它返回每个父想法的计数,并将其置于循环之外:

$parentcount = mysqli_query($con, ("SELECT parent_id, count(*) FROM tbl_menu GROUP BY parent_id");

可能还有其他问题,因此请同时发布您正在使用的数据库结构和记录数。

不要进行递归查询。

  1. "超过 1000 行"不是太大。 您可以简单地将表中的所有内容调用到 php 中,然后在 php 中执行递归 html 构建,这将有内存开销,但处理开销要少得多,因为您只对数据库进行一次访问。

  2. 或者(当您的数据库表太大时(,您应该通过添加新列来避免不必要地收集行。 新列将在插入行时存储相应行的所有"后代",或在更新行时更新它。 然后,您只需在需要调用特定行时引用此列。 换句话说,只执行一次递归处理(写入数据库时(,而不是在需要显示数据时。 这将再次在一个查询中生成一个有限的结果集,然后可以递归遍历该结果集以构建所需的输出。

基本上你需要按照@spudly的建议去做。 但是他的解决方案中有一个小问题,根据您tbl_menu表中的行数,您可以使用一大块内存来获取所有记录。 您可以使用他的解决方案进行更多优化,但将查询更改为:

select
parent_tbl_menu.id,
count(child_tbl_menu.id) as cnt
from
tbl_menu as parent_tbl_menu
left join
tbl_menu as child_tbl_menu
on parent_tbl_menu.id = child_tbl_menu.parent_id
where
parent_tbl_menu.parent_id = ?
group by
parent_tbl_menu.id

这样,您将仅获取特定父级的子记录。 请考虑使用预准备语句,因为您的代码存在 sql 注入漏洞。

  • 整个网页只连接一次(从PHP到MySQL(。
  • 如果可以在单个SELECT中完成所有工作,请不要将SELECT放在循环中,例如使用JOIN。 (例外:"分层"表需要嵌套SELECT。 例外的例外:MySQL 8.0和MariaDB 10.2可以使用"递归CTE"来完成。
  • 不要获取所有列(SELECT *(,当你想要的只是一个recordcount。 相反,SELECT COUNT(*) ...并使用返回的数字。
  • 对于一个网页来说,1000 个东西可能太多了。 重新思考用户界面。

相关内容

最新更新