zblog后台发文章超级慢的问题排查:
zb_system/cmd.php
case 'ArticlePst':
...
$zbp->BuildModule(); #慢 对应 zb_system/function/lib/zblogphp.php ZBlogPHP 的 BuildModule()
#die('ArticlePst');
zb_system/function/lib/zblogphp.php
/**
* 生成所有进Ready List的模块的Content内容并保存.
*/
public function BuildModule()
{
foreach ($GLOBALS['hooks']['Filter_Plugin_Zbp_BuildModule'] as $fpname => &$fpsignal) {
$fpname();
}
ModuleBuilder::Build(); # 慢 对应 zb_system/function/lib/modulebuilder.php ModuleBuilder 的 Build()
#die("BuildModule");
}
zb_system/function/lib/modulebuilder.php
public static function Build()
...
$num = 0;
foreach (self::$Ready as $m) {
if (isset($zbp->modulesbyfilename[$m])) {
$num = $num + 1;
if ($num == 6) {
print($m . "\n"); # 'archives' 时慢 下面 Build 慢
#$zbp->modulesbyfilename[$m]->Build(); # 慢慢慢 对应 zb_system/function/lib/base/module.php Base__Module 的 Build()
die('ModuleBuilder::Build()');
}
$zbp->modulesbyfilename[$m]->Build();
$zbp->modulesbyfilename[$m]->Save();
}
}
zb_system/function/lib/base/module.php
public function Build()
{
if ($this->NoRefresh == true) {
return;
}
/*
$this->FileName 值为 previous (翻译:最近发表)
ModuleBuilder::$List[$this->FileName] 即 ModuleBuilder::$List['previous'] 值为:
Array
(
[filename] => previous
[function] => ModuleBuilder::LatestArticles
[parameters] => Array
(
)
)
*/
if (isset(ModuleBuilder::$List[$this->FileName])) {
/*
if ($this->FileName == 'archives') {
echo 'Build()';
#print_r(ModuleBuilder::$List[$this->FileName]['function']); # 输出: ModuleBuilder::Archives
#print_r(ModuleBuilder::$List[$this->FileName]['parameters']); # 输出: Array ()
die();
}
*/
if (isset(ModuleBuilder::$List[$this->FileName]['function'])) {
$f = ModuleBuilder::$List[$this->FileName]['function'];
$p = ModuleBuilder::$List[$this->FileName]['parameters'];
$p = is_array($p) ? $p : array();
if ($this->FileName == 'archives') {
echo 'Build()';
print_r($f); # 输出: ModuleBuilder::Archives
print_r(ParseFilterPlugin($f)); # 输出: Array( [0] => ModuleBuilder [1] => Archives )
echo "<br>\n" . gettype($f); # 输出: string
echo "<br>\n" . gettype(ParseFilterPlugin($f)); # 输出:array
die();
}
# call_user_func_array 第一个参数函数名 第二个参数函数参数数组
# 如果调用类方法: 第一个参数 是数组,第一个值是类名,第二个值是方法名,[$object, 'methodName']
# 执行 ModuleBuilder::Archives() 慢
$this->Content = call_user_func_array(ParseFilterPlugin($f), $p); # 这句慢
#====>ModuleBuilder::Archives();# 最终 这句慢 zb_system/function/lib/modulebuilder.php 的 Archives()
return true;
}
}
return false;
}
#function ParseFilterPlugin($fpname) 在 zb_system/function/c_system_plugin.php
zb_system/function/lib/modulebuilder.php
public static function Archives()
{
global $zbp;
$template = $zbp->template;
#print_r($template); #Template Object ...
$tags = array();
$urls = array(); //array(url,name,count);
$maxli = $zbp->modulesbyfilename['archives']->MaxLi;# 0
#print_r($zbp->modulesbyfilename['archives']->MaxLi);
if ($maxli < 0) {
return '';
}
$sql = $zbp->db->sql->Select($zbp->table['Post'], array('log_PostTime'), null, array('log_PostTime' => 'DESC'), array(1), null);
# SELECT log_PostTime FROM zbp_post ORDER BY log_PostTime DESC LIMIT 1
# 就这一句慢啊啊 解决办法 OPTIMIZE TABLE zbp_post;
print_r($sql);
die('error');
SELECT log_PostTime FROM zbp_post ORDER BY log_PostTime DESC LIMIT 1 数据库只有几条数据 但是仍然要十几秒
原因是 在MySQL中,当表经历了大量数据的插入和删除操作后,可能会导致表的碎片化和索引的不连续,从而影响查询性能。
使用 OPTIMIZE TABLE 命令来重建表和索引,这有助于消除碎片。
这个命令会重新组织表的物理存储结构,并重建所有索引,从而可能显著提高查询性能。
对于正常使用数据库(增删改查操作),OPTIMIZE TABLE 可能会产生以下影响:
锁定表:在执行 OPTIMIZE TABLE 时,表可能会被锁定,这意味着其他用户将无法对表进行写入操作(INSERT、UPDATE、DELETE)。读取操作(SELECT)可能会受到影响,具体取决于锁的类型和持续时间。然而,对于InnoDB表,锁定通常是短暂的,并且MySQL会尽量减小锁定对并发操作的影响。
系统资源消耗:OPTIMIZE TABLE 是一个重量级操作,可能会消耗大量的系统资源(如CPU、内存和I/O)。因此,在生产环境中执行此操作时,应谨慎考虑其对系统性能的影响,并尽量在业务低峰期进行。
二进制日志(binlog):该操作会产生大量的二进制日志,如果你的主从复制环境中主库的binlog传输到从库较慢,可能会导致从库延迟增加。
综上所述,OPTIMIZE TABLE 不会删除数据,但可能会影响数据库的并发操作和系统性能。因此,在执行此操作之前,建议评估其对业务的影响,并在合适的时间窗口内进行。同时,考虑使用数据库的自动优化功能(如InnoDB的自动碎片整理)来减少手动执行 OPTIMIZE TABLE 的频率。
定期运行数据库维护任务,如 OPTIMIZE TABLE 和 ANALYZE TABLE,以保持表和索引的性能。
ANALYZE TABLE 命令会更新表的统计信息,帮助优化器做出更好的决策。
如 ANALYZE TABLE zbp_post;