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, LOG(10, 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)");
 }
 
 /**

