Index: modules/system/system.install =================================================================== RCS file: /cvs/drupal/drupal/modules/system/system.install,v retrieving revision 1.107 diff -u -p -r1.107 system.install --- modules/system/system.install 14 May 2007 16:22:26 -0000 1.107 +++ modules/system/system.install 16 May 2007 00:42:52 -0000 @@ -290,9 +290,11 @@ function system_install() { last_comment_timestamp int NOT NULL default '0', last_comment_name varchar(60) default NULL, last_comment_uid int NOT NULL default '0', + last_update_timestamp int NOT NULL default '0', comment_count int unsigned NOT NULL default '0', PRIMARY KEY (nid), KEY node_comment_timestamp (last_comment_timestamp) + KEY last_update_timestamp (last_update_timestamp) ) /*!40100 DEFAULT CHARACTER SET UTF8 */ "); db_query("CREATE TABLE {files} ( @@ -785,10 +787,12 @@ function system_install() { last_comment_timestamp int NOT NULL default '0', last_comment_name varchar(60) default NULL, last_comment_uid int NOT NULL default '0', + last_update_timestamp int NOT NULL default '0', comment_count int_unsigned NOT NULL default '0', PRIMARY KEY (nid) )"); db_query("CREATE INDEX {node_comment_statistics}_node_comment_timestamp_idx ON {node_comment_statistics} (last_comment_timestamp)"); + db_query("CREATE INDEX {node_comment_statistics}_last_update_timestamp_idx ON {node_comment_statistics} (last_update_timestamp)"); db_query("CREATE TABLE {files} ( fid serial CHECK (fid >= 0), @@ -3943,6 +3947,69 @@ function system_update_6015() { } /** + * Add a last_update_timestamp column to the {node_comment_statistics} + * table so that the performance of the tracker query isn't so deadly. + */ +function system_update_6016() { + $ret = array(); + + // Rename the existing table, define a new table with the right + // columns, but don't put on the additional indexes until we're done + // populating it. + switch ($GLOBALS['db_type']) { + case 'pgsql': + // Drop the old indexes, first. + $ret[] = update_sql("DROP INDEX {node_comment_statistics}_node_comment_timestamp_idx"); + $ret[] = update_sql("DROP INDEX {node_comment_statistics}_last_update_timestamp_idx"); + $ret[] = update_sql('ALTER TABLE {node_comment_statistics} RENAME TO {node_comment_statistics_tmp}'); + $ret[] = update_sql("CREATE TABLE {node_comment_statistics} ( + nid serial CHECK (nid >= 0), + last_comment_timestamp int NOT NULL default '0', + last_comment_name varchar(60) default NULL, + last_comment_uid int NOT NULL default '0', + last_update_timestamp int NOT NULL default '0', + comment_count int_unsigned NOT NULL default '0', + PRIMARY KEY (nid) + )"); + break; + case 'mysql': + case 'mysqli': + $ret[] = update_sql('RENAME TABLE {node_comment_statistics} TO {node_comment_statistics_tmp}'); + $ret[] = update_sql("CREATE TABLE {node_comment_statistics} ( + nid int unsigned NOT NULL auto_increment, + last_comment_timestamp int NOT NULL default '0', + last_comment_name varchar(60) default NULL, + last_comment_uid int NOT NULL default '0', + last_update_timestamp int NOT NULL default '0', + comment_count int unsigned NOT NULL default '0', + PRIMARY KEY (nid) + ) /*!40100 DEFAULT CHARACTER SET UTF8 */ "); + break; + } + + // Populate the new table + $ret[] = update_sql("INSERT INTO {node_comment_statistics} (nid, last_comment_timestamp, last_comment_name, last_comment_uid, last_update_timestamp, comment_count) SELECT ncs.nid, ncs.last_comment_timestamp, ncs.last_comment_name, ncs.last_comment_uid, GREATEST(ncs.last_comment_timestamp, n.changed), ncs.comment_count FROM {node_comment_statistics_tmp} ncs INNER JOIN {node} n ON ncs.nid = n.nid"); + + // Add the indexes + switch ($GLOBALS['db_type']) { + case 'pgsql': + $ret[] = update_sql("CREATE INDEX {node_comment_statistics}_node_comment_timestamp_idx ON {node_comment_statistics} (last_comment_timestamp)"); + $ret[] = update_sql("CREATE INDEX {node_comment_statistics}_last_update_timestamp_idx ON {node_comment_statistics} (last_update_timestamp)"); + // While we're in a pgsql-specific block, drop the old indexes, too. + break; + case 'mysql': + case 'mysqli': + $ret[] = update_sql("ALTER TABLE {node_comment_statistics} ADD KEY node_comment_timestamp (last_comment_timestamp)"); + $ret[] = update_sql("ALTER TABLE {node_comment_statistics} ADD KEY last_update_timestamp (last_update_timestamp)"); + break; + } + // Finally, drop the tmp table. + $ret[] = update_sql("DROP TABLE {node_comment_statistics_tmp}"); + + return $ret; +} + +/** * @} End of "defgroup updates-5.x-to-6.x" * The next series of updates should start at 7000. */ Index: modules/comment/comment.module =================================================================== RCS file: /cvs/drupal/drupal/modules/comment/comment.module,v retrieving revision 1.542 diff -u -p -r1.542 comment.module --- modules/comment/comment.module 14 May 2007 13:43:35 -0000 1.542 +++ modules/comment/comment.module 16 May 2007 00:42:53 -0000 @@ -470,7 +470,7 @@ function comment_nodeapi(&$node, $op, $a break; case 'insert': - db_query('INSERT INTO {node_comment_statistics} (nid, last_comment_timestamp, last_comment_name, last_comment_uid, comment_count) VALUES (%d, %d, NULL, %d, 0)', $node->nid, $node->created, $node->uid); + db_query('INSERT INTO {node_comment_statistics} (nid, last_comment_timestamp, last_comment_name, last_comment_uid, last_update_timestamp, comment_count) VALUES (%d, %d, NULL, %d, %d, 0)', $node->nid, $node->created, $node->uid, $node->changed); break; case 'delete': @@ -2008,13 +2008,13 @@ function _comment_update_node_statistics // comments exist if ($count > 0) { $last_reply = db_fetch_object(db_query_range('SELECT cid, name, timestamp, uid FROM {comments} WHERE nid = %d AND status = %d ORDER BY cid DESC', $nid, COMMENT_PUBLISHED, 0, 1)); - db_query("UPDATE {node_comment_statistics} SET comment_count = %d, last_comment_timestamp = %d, last_comment_name = '%s', last_comment_uid = %d WHERE nid = %d", $count, $last_reply->timestamp, $last_reply->uid ? '' : $last_reply->name, $last_reply->uid, $nid); + db_query("UPDATE {node_comment_statistics} SET comment_count = %d, last_comment_timestamp = %d, last_comment_name = '%s', last_comment_uid = %d, last_update_timestamp = %d WHERE nid = %d", $count, $last_reply->timestamp, $last_reply->uid ? '' : $last_reply->name, $last_reply->uid, $last_reply->timestamp, $nid); } // no comments else { - $node = db_fetch_object(db_query("SELECT uid, created FROM {node} WHERE nid = %d", $nid)); - db_query("UPDATE {node_comment_statistics} SET comment_count = 0, last_comment_timestamp = %d, last_comment_name = '', last_comment_uid = %d WHERE nid = %d", $node->created, $node->uid, $nid); + $node = db_fetch_object(db_query("SELECT uid, created, changed FROM {node} WHERE nid = %d", $nid)); + db_query("UPDATE {node_comment_statistics} SET comment_count = 0, last_comment_timestamp = %d, last_comment_name = '', last_comment_uid = %d, last_update_timestamp = %d WHERE nid = %d", $node->created, $node->uid, $node->changed, $nid); } } Index: modules/node/node.module =================================================================== RCS file: /cvs/drupal/drupal/modules/node/node.module,v retrieving revision 1.813 diff -u -p -r1.813 node.module --- modules/node/node.module 15 May 2007 05:43:16 -0000 1.813 +++ modules/node/node.module 16 May 2007 00:42:55 -0000 @@ -703,6 +703,12 @@ function node_save(&$node) { db_query($node_query, $node_table_values); db_query($revisions_query, $revisions_table_values); + // Record the last_update time. If this is a new node, + // comment_nodeapi() will add the record, so we don't have to. + if (!$node->is_new) { + db_query("UPDATE {node_comment_statistics} SET last_update_timestamp = %d WHERE nid = %d", $node->changed, $node->nid); + } + // Call the node specific callback (if any): if ($node->is_new) { node_invoke($node, 'insert'); Index: modules/tracker/tracker.module =================================================================== RCS file: /cvs/drupal/drupal/modules/tracker/tracker.module,v retrieving revision 1.147 diff -u -p -r1.147 tracker.module --- modules/tracker/tracker.module 30 Apr 2007 17:03:29 -0000 1.147 +++ modules/tracker/tracker.module 16 May 2007 00:42:57 -0000 @@ -82,16 +82,15 @@ function tracker_page($uid = 0) { // Add CSS drupal_add_css(drupal_get_path('module', 'tracker') .'/tracker.css', 'module', 'all', FALSE); - // TODO: These queries are very expensive, see http://drupal.org/node/105639 if ($uid) { - $sql = 'SELECT DISTINCT(n.nid), n.title, n.type, n.changed, n.uid, u.name, GREATEST(n.changed, l.last_comment_timestamp) AS last_updated, l.comment_count FROM {node} n INNER JOIN {node_comment_statistics} l ON n.nid = l.nid INNER JOIN {users} u ON n.uid = u.uid LEFT JOIN {comments} c ON n.nid = c.nid AND (c.status = %d OR c.status IS NULL) WHERE n.status = 1 AND (n.uid = %d OR c.uid = %d) ORDER BY last_updated DESC'; + $sql = 'SELECT DISTINCT(n.nid), n.title, n.type, n.changed, n.uid, u.name, l.last_update_timestamp AS last_updated, l.comment_count FROM {node} n INNER JOIN {node_comment_statistics} l ON n.nid = l.nid INNER JOIN {users} u ON n.uid = u.uid LEFT JOIN {comments} c ON n.nid = c.nid AND (c.status = %d OR c.status IS NULL) WHERE n.status = 1 AND (n.uid = %d OR c.uid = %d) ORDER BY last_updated DESC'; $sql = db_rewrite_sql($sql); $sql_count = 'SELECT COUNT(DISTINCT(n.nid)) FROM {node} n LEFT JOIN {comments} c ON n.nid = c.nid AND (c.status = %d OR c.status IS NULL) WHERE n.status = 1 AND (n.uid = %d OR c.uid = %d)'; $sql_count = db_rewrite_sql($sql_count); $result = pager_query($sql, 25, 0, $sql_count, COMMENT_PUBLISHED, $uid, $uid); } else { - $sql = 'SELECT DISTINCT(n.nid), n.title, n.type, n.changed, n.uid, u.name, GREATEST(n.changed, l.last_comment_timestamp) AS last_updated, l.comment_count FROM {node} n INNER JOIN {users} u ON n.uid = u.uid INNER JOIN {node_comment_statistics} l ON n.nid = l.nid WHERE n.status = 1 ORDER BY last_updated DESC'; + $sql = 'SELECT DISTINCT(n.nid), n.title, n.type, n.changed, n.uid, u.name, l.last_update_timestamp AS last_updated, l.comment_count FROM {node} n INNER JOIN {users} u ON n.uid = u.uid INNER JOIN {node_comment_statistics} l ON n.nid = l.nid WHERE n.status = 1 ORDER BY last_updated DESC'; $sql = db_rewrite_sql($sql); $sql_count = 'SELECT COUNT(n.nid) FROM {node} n WHERE n.status = 1'; $sql_count = db_rewrite_sql($sql_count);