Just some friendly developer advice, you can chose to look at this and implement or not, but I would suggest either following what I did or the developer may have a better solution I didn't think of. I ran an EXPLAIN query on this SELECT query since it showed up in my slow queries log
PHP Code:
$force_thread = $db->query_first("
SELECT *
FROM " . TABLE_PREFIX . "thread AS thread
LEFT JOIN " . TABLE_PREFIX . "force_read_users AS force_read_users ON (thread.threadid = force_read_users.force_read_threadid AND force_read_users.force_read_userid = '".$vbulletin->userinfo['userid']."')
WHERE thread.force_read = '1' AND (thread.force_read_expire_date = '0' OR thread.force_read_expire_date > '".TIMENOW."') AND (". implode(' OR ', $where_usergroups) .") AND (". implode(' OR ', $where_forums) .") AND force_read_users.force_read_userid IS NULL
ORDER BY force_read_order ASC
");
Obviously I entered in some values into it to make the variables work in phpMyAdmin. Here's what i found with my relatively small forum:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE thread
ALL NULL NULL NULL NULL
11877 Using where; Using filesort
1 SIMPLE force_read_users eq_ref PRIMARY PRIMARY 8 const,temp1.thread.threadid 1 Using where; Using index; Not exists
I added a index to the 'thread.force_read' row (since its boolean and a super small length) and heres the improvement
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE thread
ref force_read force_read 1 const
18 Using where; Using filesort
1 SIMPLE force_read_users eq_ref PRIMARY PRIMARY 8 const,temp1.thread.threadid 1 Using where; Using index; Not exists
Should give you a MUCH more efficient query, I only have a few threads in my forum that we use the force read for (like for new rules), so I would think a site that uses this all the time with a lot more threads would see a substantial improvement
PS apologize for the terrible formatting of the exlpain query, never could line up columns easy on vbulletin