优化表结构
另外,SQL的缓慢可能是由于,第3方模块中SQL表的不良实现引起的。例如,列没有索引的话就会引起查询缓慢。一个快速查看MySQL如何执行查询的方式是,从你的缓慢查询日志中取出一个查询,在其前面加上单词EXPLAIN,然后将这个查询发给MySQL。那么结果就是得到了一个显示使用了哪些索引的表。更多信息可参看MySQL的相关书籍。
手工缓存查询语句
如果你必须要进行一些非常昂贵的查询,那么你可以在你的模块中手工的将结果缓存起来。关于Drupal缓存API的更多详细信息,参看第15章。
将表类型从MyISAM改为InnoDB
MySQL有两种常见的存储引擎,通常也称为表类型,它们是MyISAM 和InnoDB。Drupal默认使用的是MyISAM。
为了测试表级锁是不是引起性能缓慢的原因,你可以通过在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命令。