You are here

Drupal专业开发指南 第22章 优化表结构

优化表结构

另外,SQL的缓慢可能是由于,第3方模块中SQL表的不良实现引起的。例如,列没有索引的话就会引起查询缓慢。一个快速查看MySQL如何执行查询的方式是,从你的缓慢查询日志中取出一个查询,在其前面加上单词EXPLAIN,然后将这个查询发给MySQL。那么结果就是得到了一个显示使用了哪些索引的表。更多信息可参看MySQL的相关书籍。
 
手工缓存查询语句
    如果你必须要进行一些非常昂贵的查询,那么你可以在你的模块中手工的将结果缓存起来。关于Drupal缓存API的更多详细信息,参看第15章。
 
将表类型从MyISAM改为InnoDB
MySQL有两种常见的存储引擎,通常也称为表类型,它们是MyISAM 和InnoDB。Drupal默认使用的是MyISAM。
MyISAM使用表级别的锁机制,而InnoDB使用行级别的锁机制。锁对于数据库的完整性非常重要;它可以避免两个数据库进程同时对同一数据进行更新操作。在实际中,锁机制策略的不同意味着当你对MyISAM表进行写操作时,整个表将被锁住。因此,在一个繁忙的Drupal站点上,当正在添加多个评论时,在插入一个新评论的同时所有的评论都不能被读取。而在InnoDB上,这就不是一个问题,因为只有正被插入的那一行被锁住了,从而允许其它的服务器线程对其它各行继续进行操作。然而,在MyISAM中,表的读取更快,而数据维护和恢复工具更加完善。MySQL表的存储架构的更多信息,参看http://dev.mysql.com/tech-resources/articles/storage-engine/part_1.html或者http://dev.mysql.com/doc/refman/5.1/en/storage-engines.html
为了测试表级锁是不是引起性能缓慢的原因,你可以通过在MySQL中检查状态变量Table_locks_immediate和Table_locks_waited的值来分析锁的竞争程度。
 
mysql> SHOW STATUS LIKE 'Table%';
 
+-----------------------+---------+
| Variable_name         | Value     |
+-----------------------+---------+
| Table_locks_immediate | 1151552  |
| Table_locks_waited    | 15324     |
+-----------------------+---------+
 
Table_locks_immediate指的是能够立即获得表级锁的次数,而Table_locks_waited指的是不能立即获取表级锁而需要等待的次数。如果Table_locks_waited的值比较大的话,并且你遇到了性能问题,你可能希望将大表切分成小表;例如,你可以为一个定制模块创建一个专有的缓存(cache)表,或者通过其它方式来减小表的大小,或者降低表级锁命令调用的频率。对于一些表,比如cache_*,Watchdog, 和 accesslog表,减少表的大小的一种方式是减少数据的生命周期。使用Drupal的后台管理接口可以设置数据的生命周期。还有,确保每小时能够运行一次cron,从而能够不断的清理这些表中的过期数据。
因为Drupal可以运行在不同的应用下,所以不可能一刀切的具体到某个表就应该使用某个表引擎。然而,一般情况下,适合转变为InnoDB的表有cache, watchdog, sessions, 和 accesslog 表。幸运的是,转变到InnoDB上非常简单:
 
ALTER TABLE accesslog TYPE='InnoDB';
 
当然,这一转变应该在站点下线并且已经为你的数据做好备份时进行,而且你也应该首先了解InnoDB表的不同特性。
 
注意 尽管数据库API提供了db_lock_table() 和db_unlock_tables()函数供第3方模块使用,但是Drupal6中,核心代码并没有使用LOCK TABLES命令。
 
关于MySQL的性能调优,参看http://www.day32.com/MySQL/的性能调优脚本,这里提供了调整MySQL服务器变量的建议。

Drupal版本: