Index: modules/search/search.module =================================================================== RCS file: /cvs/drupal/drupal/modules/search/search.module,v retrieving revision 1.256 diff -u -u -p -r1.256 search.module --- modules/search/search.module 6 May 2008 12:18:50 -0000 1.256 +++ modules/search/search.module 13 May 2008 13:02:51 -0000 @@ -278,24 +278,22 @@ function search_cron() { * up to date (even if cron times out or otherwise fails). */ function search_update_totals() { - // Update word IDF (Inverse Document Frequency) counts for new/changed words - foreach (search_dirty() as $word => $dummy) { - // Get total count - $total = db_result(db_query("SELECT SUM(score) FROM {search_index} WHERE word = '%s'", $word)); - // Apply Zipf's law to equalize the probability distribution - $total = log10(1 + 1/(max(1, $total))); - db_query("UPDATE {search_total} SET count = %f WHERE word = '%s'", $total, $word); - if (!db_affected_rows()) { - db_query("INSERT INTO {search_total} (word, count) VALUES ('%s', %f)", $word, $total); - } + // Update the search totals in chunks of 500 words at a time, + // This prevents using too big of a SQL clause. + $dirty = array_keys(search_dirty()); + while (count($dirty) > 0) { + $dirty500 = array_splice($dirty, 0, 500); + $placeholders = db_placeholders($dirty500, 'varchar'); + db_query("DELETE FROM {search_total} WHERE word IN (". $placeholders .")", $dirty500); + // Update word IDF (Inverse Document Frequency) counts for new/changed words, + // Applying Zipf's law to equalize the probability distribution + db_query("INSERT INTO {search_total} SELECT word, LOG10(1+1/GREATEST(1, SUM(score))) FROM {search_index} WHERE WORD IN (". $placeholders .") GROUP BY word", $dirty500); } + // Find words that were deleted from search_index, but are still in // search_total. We use a LEFT JOIN between the two tables and keep only the // rows which fail to join. - $result = db_query("SELECT t.word AS realword, i.word FROM {search_total} t LEFT JOIN {search_index} i ON t.word = i.word WHERE i.word IS NULL"); - while ($word = db_fetch_object($result)) { - db_query("DELETE FROM {search_total} WHERE word = '%s'", $word->realword); - } + db_query("DELETE FROM {search_total} WHERE word IN (SELECT t.word AS realword FROM {search_total} t LEFT JOIN {search_index} i ON t.word = i.word WHERE i.word IS NULL)"); } /**