在每个页面加载时自动索引,修复和优化MySQL表

时间:2011-12-30 18:20:40

标签: php mysql

我和一个男人在辩论,告诉我使用他的功能没有表现出色......

每个运行页面的用户在每个页面加载时使用PHP类__destruct()自动索引,修复和优化MySQL表。

他问我为什么我觉得这对表现不好但是我真的不知道,有人能告诉我为什么这样的事情不好吗?

更新他的推理......

优化&修复数据库表消除了开销的字节大小,当涉及多个连接和表使用时,这会大大减慢其他查询的速度。即使启用了索引的性能增强的数据库模式。

更不用说执行这些操作的执行时间在内存和处理器线程中都是微不足道的。

打开,阅读,写作,更新,然后清理自己对我更有意义,然后执行相同的操作,并在等待cron条目清理后留下不必要的开销。

5 个答案:

答案 0 :(得分:6)

为什么不衡量呢?使用工具包来分析您花时间的位置,例如Instrumentation for PHP。证明PHP请求的优化步骤需要很长时间。

重新索引是一个昂贵的过程,至少与执行表扫描一样昂贵,就好像你没有索引一样。您应该不经常构建索引,以便在每次构建索引时借助索引提供许多PHP请求。如果您正在为每个PHP请求构建索引,那么您可能根本不会定义索引,而只是一直运行表扫描。

REPAIR TABLE仅与MyISAM表(和存档表)相关。我不建议使用MyISAM表。你应该只使用InnoDB表。不仅是为了性能,还为了数据安全。 MyISAM非常容易受到数据损坏的影响,而InnoDB在大多数情况下通过维护每页的内部校验和来防范这种情况。

InnoDB表的OPTIMIZE TABLE重建 all 数据和索引页面。一旦你的桌子增长到一个非平凡的大小,这将是非常昂贵的。当然不是你想要在每个页面加载上做的事情。我甚至会说在任何 PHP Web请求期间不应该执行OPTIMIZE TABLE - 通过某些脚本或管理界面脱机执行。

表重组也会锁定表。您将排队访问同一个表很长时间的所有其他PHP请求(即几分钟甚至几小时,具体取决于表的大小)。当每个PHP请求都有机会时,它将运行另一个表重组。在每个PHP请求上产生这么多的开销是荒谬的。


您也可以使用类比:您不会在每次PHP请求期间重建或优化整个表或索引,原因与您每次启动时都不会让您的汽车进行调整和换油一样:
这样做既昂贵又不方便,与在适当的时间表上进行发动机维护相比,它没有任何额外的好处。

答案 1 :(得分:4)

因为每一项操作(索引,修复和优化)都需要相当长的时间;事实上,如果表格甚至略大,它们非常昂贵(表锁,磁盘IO,数据丢失的风险)。

绝对不建议在每个页面加载时执行此操作。它应该只在需要时完成。

答案 2 :(得分:3)

修复表可能导致数据丢失,如文档中所述,因此需要先前备份以避免进一步的问题。此外,它仅在灾难发生时运行(HAS失败)。

优化表会阻止维护中的表,因此可能会导致并发用户出现问题。

我的0.02:数据库管理操作不应该是常见用户事务的一部分,因为随着表的增长,它们的时间和资源都很昂贵。

答案 3 :(得分:2)

我已经将以下代码设置为每天清晨运行的预定作业,当用户不经常访问我们的网站时(我读到OPTIMIZE应该在优化期间锁定受影响的表)。

使用此函数的优点是单个查询由所有以逗号分隔的表名组成,而是执行大量查询,每个表对应一个优化。

假设您已打开数据库连接并选择了数据库,以便在不指定数据库连接,数据库名称等的情况下使用此功能。

$q = "SHOW TABLE STATUS WHERE Data_Free > '0'";
$res = mysql_query($q); $TOOPT = mysql_num_rows($res);
$N = 0; // number of optimized tables
if(mysql_num_rows($res) > 0)
{
        $N = 1;
        while($t = mysql_fetch_array($res))
        {
            $TNAME = $t['Name']; $TSPACE += $t['Data_free'];
            if($N < 2)
            {
                $Q  = "OPTIMIZE TABLE ".$TNAME."";
            }
            else
            {
                $Q .= ", ".$TNAME."";
            }
            $N++;
        } // endwhile tables
        mysql_query($Q);
} // endif tables found (to optimize)

答案 4 :(得分:0)

文档说明......

optimize reference

  

如果删除了很大一部分,则应使用OPTIMIZE TABLE   表或者如果您对具有可变长度的表进行了许多更改   行(具有VARCHAR,VARBINARY,BLOB或TEXT列的表)。   删除的行在链表和后续INSERT中维护   操作重用旧行位置。您可以使用OPTIMIZE TABLE   回收未使用的空间并对数据文件进行碎片整理。后   对表格进行了大量更改,此声明也可能会有所改进   使用该表的语句的性能,有时是显着的。

执行操作时,使用'OPTIMIZE'命令可以提高性能。

flush reference

  

FLUSH TABLES有几种变体形式。 FLUSH TABLE是的同义词   FLUSH TABLES,除了TABLE不能与WITH READ LOCK一起使用   变体。

使用'FLUSH TABLE'命令与'FLUSH TABLES'没有执行READ LOCK。

repair reference

  

通常,您永远不必运行REPAIR TABLE。但是,如果   灾难来袭,这句话非常有可能让你全部收回   来自MyISAM表的数据。如果你的表经常被破坏,那么你   应尽量找到它的原因,以消除使用的必要性   修理表。请参见第C.5.4.2节“如果MySQL保留怎么办   崩溃“,以及第13.5.4节,”MyISAM表问题“。

我的理解是,如果'REPAIR TABLE'命令一致地运行,那么创建大记录的条件将被执行,因为执行了恒定的维护。如果我错了,我希望看到基准,因为我自己的尝试没有显示任何太有害的,尽管记录集已经低于10k标记。

以下是正在使用的代码,@ codedev正在询问......

class db
{
 protected static $dbconn;

 // rest of database class

 public function index($link, $database)
 {
  $obj = $this->query('SHOW TABLES');
  $results = $this->results($obj);
  foreach ($results as $key => $value){
   if (isset($value['Tables_in_'.$database])){
    $this->query('REPAIR TABLE '.$value['Tables_in_'.$database]);
    $this->query('OPTIMIZE TABLE '.$value['Tables_in_'.$database]);
    $this->query('FLUSH TABLE '.$value['Tables_in_'.$database]);
   }
  }
 }
 public function __destruct()
 {
  $this->index($this->dbconn, $this->configuration['database']);
  $this->close();
 }
}