To find out which pages are the most resource intensive, enable the statistics module that is included with Drupal. Although the
statistics module increases the load on your server (since it records access statistics for your site into your database), it can
beuseful to see which pages are the most frequently viewed and thus the most ripe for query optimization. It also tracks total pagegeneration time over a period, which you can specify in Configuration -> Statistics. This is useful for identifying out-of-control
web crawlers that are eating up system resources, which you can then ban on the spot by visiting Reports -> Top visitors and
clicking “ban.” Be careful, though—it’s just as easy to ban a good crawler that drives traffic to your site as a bad one. Make sure
you investigate the origin of the crawler before banning it.
Identifying Expensive Code
Consider the following resource-hogging code:
// Very expensive, silly way to get node titles. First we get the node IDs
// of all published nodes.
$query = db_select('node', 'n');
$query->fields('n', array('nid'));
$query->condition("n.status", 1);
$query->addTag('node_access');
$result = $query->execute();
// Now we do a node_load() on each individual node and save the title.
foreach($result as $row) {
$node = node_load($row->nid);
$titles[] = check_plain($node->title);
}
Fully loading a node is an expensive operation: hooks run, modules perform database queries to add or modify the node, and memory is used to cache the node in node_load()’s internal cache. If you are not depending on modification to the node by a module, it’s
much faster to do your own query of the node table directly. Certainly this is a contrived example, but the same pattern can often befound, that is, often data is retrieved via multiple queries that could be combined into a single query, or needless node loading is
performed.
Optimizing Tables
SQL slowness can result from poor implementation of SQL tables in contributed modules. For example, columns without indices may
result in slow queries. A quick way to see how queries are executed by MySQL is to take one of the queries you’ve captured in
your slow query log, prepend the word EXPLAIN to it, and issue the query to MySQL. The result will be a table showing which indices were used. Consult a good book on MySQL for details.
Caching Queries Manually
If you have very expensive queries that must be performed, perhaps the results can be manually cached by your module. See
Chapter 16 for details on Drupal’s cache API.
Changing the Table Type from MyISAM to InnoDB
Two common choices for MySQL storage engines, often called table types, are MyISAM and InnoDB. Drupal uses InnoDB by
default.
MyISAM uses table-level locking, while InnoDB uses row-level locking. Locking is important to preserve database integrity; it
prevents two database processes from trying to update the same data at the same time. In practice, the difference in locking
strategies means that access to an entire table is blocked during writes for MyISAM. Therefore, on a busy Drupal site when many
comments are being added, all comment reads are blocked while a new comment is inserted. On InnoDB, this is less of a problem,
since only the row(s) being written get locked, allowing other server threads to continue to operate on the remaining rows.However, with MyISAM,table reads are faster, and data maintenance and recovery tools are more mature. See http://dev.mysql.com/tech-resources/articles/storage- engine/part_1.html or http://dev.mysql.com/doc/refman/5.1/en/storage-engines.html for more
information on MySQL’s table storage architectures. To test whether table-locking issues are the cause of slow performance, you
can analyze lock contention by checking the Table_locks_immediate and Table_locks_waited status variables within MySQL.
mysql> SHOW STATUS LIKE 'Table%';
+-----------------------+---------+
| Variable_name | Value |
+-----------------------+---------+
| Table_locks_immediate | 1151552 |
| Table_locks_waited | 15324 |
+-----------------------+---------+
Table_locks_immediate is the number of times that a table lock was acquired immediately, and Table_locks_waited is the number of times a table lock could not be acquired immediately and a wait was needed. If the Table_locks_waited value is high,and you
are having performance problems, you may want to split up large tables; for example, you might create a dedicated cache table for acustom module or consider ways to reduce the sizes or the frequency of the table lock commands. One way to reduce table sizes
for some tables, such as the cache_*, watchdog, and accesslog tables, is by reducing the lifetime of the data. This can be done within the Drupal administrative interface. Also, making sure cron is being run as often as once an hour will keepthese tables pruned.
Because Drupal can be used in many different ways, it is impossible to give an across-the-board recommendation as to which tables
should use which engine. However, in general, good candidates for conversion to InnoDB are the cache, watchdog, sessions, and
accesslog tables. Fortunately, the conversion to InnoDB is very simple:
ALTER TABLE accesslog TYPE='InnoDB';
Of course, this conversion should be done when the site is offline and your data has been backed up, and you should be informed about the different characteristics of InnoDB tables. For MySQL performance tuning, check out the performance tuning script at www.day32.com/MySQL/, which provides suggestions for tuning MySQL server variables.
Summary
In this chapter, you learned the following:
• How to troubleshoot performance bottlenecks.
• How to optimize a web server.
• How to optimize a database.
• Drupal-specific optimizations.
• Possible multi server architectures.
Không có nhận xét nào:
Đăng nhận xét