List:Commits« Previous MessageNext Message »
From:Luis Soares Date:November 12 2010 1:59pm
Subject:bzr commit into mysql-next-mr branch (luis.soares:3205) WL#5597
View as plain text  
#At file:///home/lsoares/Workspace/bzr/work/features/wl5597/mysql-next-mr/ based on revid:luis.soares@stripped

 3205 Luis Soares	2010-11-12
      WL#5597: Using batch operations when there is no index in RBR
      
      Work-in-progress.
      
      Improvements on this cset:
      - key to hash table contains hashed value, not the row (smaller 
        memory footprint)
      - blobs are removed from the hashing

    modified:
      sql/log_event.cc
=== modified file 'sql/log_event.cc'
--- a/sql/log_event.cc	2010-11-05 00:31:22 +0000
+++ b/sql/log_event.cc	2010-11-12 13:59:15 +0000
@@ -7762,7 +7762,7 @@ static uint decide_row_lookup_method(TAB
   uint key_index= search_key_in_table(table, cols, (PRI_KEY_FLAG | UNIQUE_KEY_FLAG | MULTIPLE_KEY_FLAG));
 
   /* No index */
-  if (key_index == MAX_KEY /* TODO: || key_index > number of keys in the table */)
+  if (key_index == MAX_KEY || key_index > table->s->keys)
     // TODO: change so that it takes into account the slave_exec_mode flag
     //res= slave_exec_mode & TABLE_SCAN ? TABLE_SCAN : HASH_SCAN;
     res= Rows_log_event::ROW_LOOKUP_HASH_SCAN;
@@ -7883,11 +7883,26 @@ record_compare_exit:
   return result;
 }
 
+/**
+   Hashing commodity structures and functions.
+ */ 
 
 struct row_entry
 {
-  uchar *key;
+  uchar* key;
+
+  /**
+     Length of the key.
+   */
   uint length;
+
+  my_hash_value_type hash_value;
+
+  /** 
+     Points at the position where the row starts in the
+     event buffer (ie, area in memory before unpacking takes
+     place).
+  */
   const uchar *m_curr_row;
 } typedef row_entry;
 
@@ -7905,28 +7920,78 @@ extern "C" uchar *rows_log_event_get_key
 static void rows_log_event_free_entry(row_entry *entry)
 {
   DBUG_ENTER("free_entry");
-  my_free(entry->key);
   my_free(entry);
   DBUG_VOID_RETURN;
 }
 
+int remove_blobs_from_record(TABLE* table)
+{ 
+  int res= 0;
+
+  if (table->s->blob_fields)
+  {
+    for (Field **ptr=table->field ; *ptr ; ptr++)
+    {
+      Field *field= *ptr;
+      if (field->type() == MYSQL_TYPE_BLOB)
+      {
+        field->reset();
+        field->set_null(); // careful the table may have a not null constraint on this field
+        res++;
+      }
+    }
+  }
+
+  return res;
+}
+
+bool
+row_hash_insert(HASH* info, uchar* record, int reclength, const uchar* curr_row)
+{
+  row_entry *entry= (row_entry*) malloc(sizeof(row_entry));
+  if (!entry)
+  {
+    return true;
+  }
+
+  entry->key= (uchar*)&entry->hash_value;
+  entry->length= sizeof(my_hash_value_type);
+
+  entry->hash_value= my_calc_hash(info, record, reclength);
+  entry->m_curr_row=(const uchar *) curr_row;
+  my_hash_insert(info, (uchar *) entry);
+
+  return false;
+}
+
 int Rows_log_event::hash_row(Relay_log_info const *rli)
 {
   int error= 0;
 
+  /**
+     Unpack the row to be hashed.
+   */ 
   if ((error= unpack_current_row(rli, &m_cols)))
     goto err;
+
   else
   {
-    // TODO: remove blobs
+    /**
+       Save a copy of the original record unpacked.
+     */ 
+    store_record(m_table, record[1]);
 
-    row_entry *entry= (row_entry*)malloc(sizeof(row_entry));
-    entry->key= (uchar*) malloc(m_table->s->reclength);
-    memcpy(entry->key, m_table->record[0], m_table->s->reclength);
-    entry->length= m_table->s->reclength;
-    entry->m_curr_row=m_curr_row;
-    my_hash_insert(&m_hash, (uchar*)entry);
+    /**
+       Remove the blobs from the record.
+     */
+    remove_blobs_from_record(m_table);
 
+    row_hash_insert(&m_hash, m_table->record[0], m_table->s->reclength, m_curr_row);
+
+    /**
+       Restore back record[0], just to be safe.
+     */
+    memcpy(m_table->record[0], m_table->record[1], m_table->s->reclength);
 
     if (get_type_code() == UPDATE_ROWS_EVENT)
     {
@@ -8312,27 +8377,44 @@ int Rows_log_event::do_hash_scan_and_upd
     {
       error= table->file->ha_rnd_next(table->record[0]);
 
-      // TODO: remove blobs from record got from the engine
-
       DBUG_PRINT("info", ("error: %s", HA_ERR(error)));
       switch (error) {
         case 0:
         {
           bool found_in_hash= false;
           HASH_SEARCH_STATE state;
+          my_hash_value_type se_key; /* storage engine record based row key */
+
           /* save a copy from the record got from the engine. */
           store_record(table, record[1]);
-
+          
+          /**
+             Remove the blobs from the record so that we can compare
+             the hash against the hash from record got from the
+             binlog, which was calculated without blobs as well.
+          */
+          remove_blobs_from_record(table);
+          
+          /* calculate the key */
+          se_key= my_calc_hash(&m_hash, m_table->record[0], m_table->s->reclength);
+          
           /**
              This is only needed because records are hashed without blobs, so
              we may have false positives.
            */
-          row_entry *entry= (row_entry *) my_hash_first(&m_hash, table->record[0], table->s->reclength, &state);
+          row_entry *entry= (row_entry *) my_hash_first(&m_hash, 
+                                                        (const uchar*) &se_key, 
+                                                        sizeof(my_hash_value_type), 
+                                                        &state);
           while (entry)
-          {
+          {                        
+            const uchar* key= (const uchar*) &entry->key;
+
             /**
-               unpack again the full record to table->record[0]. Now, both
-               table->record[0] and table->record[1] have the same contents.
+               unpack again the full record to table->record[0]. Now,
+               both table->record[0] and table->record[1] should have
+               approximately the same contents (except maybe for blobs
+               - thence we need to do full comparison below).
              */
             m_curr_row= entry->m_curr_row;
             if ((error= unpack_current_row(rli, &m_cols)))
@@ -8351,8 +8433,11 @@ int Rows_log_event::do_hash_scan_and_upd
               break;
             }
 
-            // find next
-            entry= (row_entry *)my_hash_next(&m_hash, table->record[0], table->s->reclength,  &state);
+            /* Next row for the loop... */
+            entry= (row_entry *)my_hash_next(&m_hash, 
+                                             key, 
+                                             sizeof(my_hash_value_type),  
+                                             &state);
           }
 
           if (found_in_hash)


Attachment: [text/bzr-bundle] bzr/luis.soares@oracle.com-20101112135915-det3crs30cllhfqi.bundle
Thread
bzr commit into mysql-next-mr branch (luis.soares:3205) WL#5597Luis Soares12 Nov