diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 371ef9787c1..7f587a31039 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -3816,9 +3816,8 @@ retry: DBUG_RETURN(HA_ERR_NO_SUCH_TABLE); } - prebuilt = row_create_prebuilt(ib_table); + prebuilt = row_create_prebuilt(ib_table, table->s->reclength); - prebuilt->mysql_row_len = table->s->reclength; prebuilt->default_rec = table->s->default_values; ut_ad(prebuilt->default_rec); diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 6d5b7b4668f..c6754660b84 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -1008,7 +1008,12 @@ ha_innobase::final_add_index( row_prebuilt_free(prebuilt, TRUE); error = row_merge_drop_table(trx, old_table); add->indexed_table->n_mysql_handles_opened++; - prebuilt = row_create_prebuilt(add->indexed_table); + prebuilt = row_create_prebuilt(add->indexed_table, + 0 /* XXX Do we know the mysql_row_len here? + Before the addition of this parameter to + row_create_prebuilt() the mysql_row_len + member was left 0 (from zalloc) in the + prebuilt object. */); } err = convert_error_code_to_mysql( diff --git a/storage/innobase/include/data0data.h b/storage/innobase/include/data0data.h index f7bdd29ed90..9435169a0fd 100644 --- a/storage/innobase/include/data0data.h +++ b/storage/innobase/include/data0data.h @@ -231,6 +231,12 @@ dtuple_set_n_fields_cmp( dtuple_t* tuple, /*!< in: tuple */ ulint n_fields_cmp); /*!< in: number of fields used in comparisons in rem0cmp.* */ + +/* Estimate the number of bytes that are going to be allocated when +creating a new dtuple_t object */ +#define DTUPLE_EST_ALLOC(n_fields) \ + (sizeof(dtuple_t) + (n_fields) * sizeof(dfield_t)) + /**********************************************************//** Creates a data tuple to a memory heap. The default value for number of fields used in record comparisons for this tuple is n_fields. @@ -240,7 +246,8 @@ dtuple_t* dtuple_create( /*==========*/ mem_heap_t* heap, /*!< in: memory heap where the tuple - is created */ + is created, DTUPLE_EST_ALLOC(n_fields) + bytes will be allocated from this heap */ ulint n_fields); /*!< in: number of fields */ /**********************************************************//** diff --git a/storage/innobase/include/data0data.ic b/storage/innobase/include/data0data.ic index 5c0f8039c80..971f58412c0 100644 --- a/storage/innobase/include/data0data.ic +++ b/storage/innobase/include/data0data.ic @@ -356,15 +356,15 @@ dtuple_t* dtuple_create( /*==========*/ mem_heap_t* heap, /*!< in: memory heap where the tuple - is created */ + is created, DTUPLE_EST_ALLOC(n_fields) + bytes will be allocated from this heap */ ulint n_fields) /*!< in: number of fields */ { dtuple_t* tuple; ut_ad(heap); - tuple = (dtuple_t*) mem_heap_alloc(heap, sizeof(dtuple_t) - + n_fields * sizeof(dfield_t)); + tuple = (dtuple_t*) mem_heap_alloc(heap, DTUPLE_EST_ALLOC(n_fields)); tuple->info_bits = 0; tuple->n_fields = n_fields; tuple->n_fields_cmp = n_fields; diff --git a/storage/innobase/include/row0mysql.h b/storage/innobase/include/row0mysql.h index dd619406ab9..27fc1b95808 100644 --- a/storage/innobase/include/row0mysql.h +++ b/storage/innobase/include/row0mysql.h @@ -168,7 +168,9 @@ UNIV_INTERN row_prebuilt_t* row_create_prebuilt( /*================*/ - dict_table_t* table); /*!< in: Innobase table handle */ + dict_table_t* table, /*!< in: Innobase table handle */ + ulint mysql_row_len); /*!< in: length in bytes of a row in + the MySQL format */ /********************************************************************//** Free a prebuilt struct for a MySQL table handle. */ UNIV_INTERN diff --git a/storage/innobase/row/row0mysql.c b/storage/innobase/row/row0mysql.c index 987d6595224..9289a2930d4 100644 --- a/storage/innobase/row/row0mysql.c +++ b/storage/innobase/row/row0mysql.c @@ -667,17 +667,60 @@ UNIV_INTERN row_prebuilt_t* row_create_prebuilt( /*================*/ - dict_table_t* table) /*!< in: Innobase table handle */ + dict_table_t* table, /*!< in: Innobase table handle */ + ulint mysql_row_len) /*!< in: length in bytes of a row in + the MySQL format */ { row_prebuilt_t* prebuilt; mem_heap_t* heap; dict_index_t* clust_index; dtuple_t* ref; ulint ref_len; + ulint search_tuple_n_fields; - heap = mem_heap_create(sizeof *prebuilt + 128); + search_tuple_n_fields = 2 * dict_table_get_n_cols(table); - prebuilt = mem_heap_zalloc(heap, sizeof *prebuilt); + clust_index = dict_table_get_first_index(table); + + /* Make sure that search_tuple is long enough for clustered index */ + ut_a(2 * dict_table_get_n_cols(table) >= clust_index->n_fields); + + ref_len = dict_index_get_n_unique(clust_index); + +#define PREBUILT_HEAP_INITIAL_SIZE \ + ( \ + sizeof(*prebuilt) \ + /* allocd in this function */ \ + + DTUPLE_EST_ALLOC(search_tuple_n_fields) \ + + DTUPLE_EST_ALLOC(ref_len) \ + /* allocd in row_prebuild_sel_graph() */ \ + + sizeof(sel_node_t) \ + + sizeof(que_fork_t) \ + + sizeof(que_thr_t) \ + /* allocd in row_get_prebuilt_update_vector() */ \ + + sizeof(upd_node_t) \ + + sizeof(upd_t) \ + + sizeof(upd_field_t) \ + * dict_table_get_n_cols(table) \ + + sizeof(que_fork_t) \ + + sizeof(que_thr_t) \ + /* allocd in row_get_prebuilt_insert_row() */ \ + + sizeof(ins_node_t) \ + /* mysql_row_len could be huge and we are not \ + sure if this prebuilt instance is going to be \ + used in inserts */ \ + + (mysql_row_len < 256 ? mysql_row_len : 0) \ + + DTUPLE_EST_ALLOC(dict_table_get_n_cols(table)) \ + + sizeof(que_fork_t) \ + + sizeof(que_thr_t) \ + ) + + /* We allocate enough space for the objects that are likely to + be created later in order to minimize the number of malloc() + calls */ + heap = mem_heap_create(PREBUILT_HEAP_INITIAL_SIZE); + + prebuilt = mem_heap_zalloc(heap, sizeof(*prebuilt)); prebuilt->magic_n = ROW_PREBUILT_ALLOCATED; prebuilt->magic_n2 = ROW_PREBUILT_ALLOCATED; @@ -695,15 +738,7 @@ row_create_prebuilt( UNIV_MEM_INVALID(&prebuilt->stored_select_lock_type, sizeof prebuilt->stored_select_lock_type); - prebuilt->search_tuple = dtuple_create( - heap, 2 * dict_table_get_n_cols(table)); - - clust_index = dict_table_get_first_index(table); - - /* Make sure that search_tuple is long enough for clustered index */ - ut_a(2 * dict_table_get_n_cols(table) >= clust_index->n_fields); - - ref_len = dict_index_get_n_unique(clust_index); + prebuilt->search_tuple = dtuple_create(heap, search_tuple_n_fields); ref = dtuple_create(heap, ref_len); @@ -720,6 +755,8 @@ row_create_prebuilt( prebuilt->autoinc_last_value = 0; + prebuilt->mysql_row_len = mysql_row_len; + return(prebuilt); }