diff --git a/mysql-8.0.19/storage/innobase/include/log0recv.h b/mysql-8.0.19/storage/innobase/include/log0recv.h index 72b5623ec..99b83aa39 100644 --- a/mysql-8.0.19/storage/innobase/include/log0recv.h +++ b/mysql-8.0.19/storage/innobase/include/log0recv.h + + +struct dummy_node { + bool reuse = false; + uint16_t n; + dict_index_t *index; +}; + +dummy_node *get_dummy_node(uint16_t n); +void restore_dummy_node(dummy_node *node); +void clear_dummy_nodes(); + +extern std::unordered_map> dummy_node_map; + + diff --git a/mysql-8.0.19/storage/innobase/include/mtr0log.h b/mysql-8.0.19/storage/innobase/include/mtr0log.h index c6baeb3c8..c07541e2a 100644 --- a/mysql-8.0.19/storage/innobase/include/mtr0log.h +++ b/mysql-8.0.19/storage/innobase/include/mtr0log.h @@ -263,7 +263,8 @@ byte *mlog_open_and_write_index( byte *mlog_parse_index(byte *ptr, /*!< in: buffer */ const byte *end_ptr, /*!< in: buffer end */ ibool comp, /*!< in: TRUE=compact record format */ - dict_index_t **index); /*!< out, own: dummy index */ + dict_index_t **index, /*!< out, own: dummy index */ + dummy_node **node); /*!< out, save node information*/ /** Parses a log record written by MLOG_INNOSQL_STATS_UPDATE. @return parsed record end, NULL if not a complete record */ diff --git a/mysql-8.0.19/storage/innobase/log/log0recv.cc b/mysql-8.0.19/storage/innobase/log/log0recv.cc index 77758d780..78aa645e3 100644 --- a/mysql-8.0.19/storage/innobase/log/log0recv.cc +++ b/mysql-8.0.19/storage/innobase/log/log0recv.cc +std::unordered_map> dummy_node_map; + @@ -1711,6 +1713,8 @@ void recv_sys_free() { } mutex_exit(&recv_sys->mutex); + + clear_dummy_nodes(); } /** Copy of the LOG_HEADER_CREATOR field. */ @@ -3413,6 +3417,72 @@ void meb_apply_log_recs_via_callback( #endif /* !UNIV_HOTBACKUP */ + +/* ------ Dummy index/table optimization ------ */ + +static dummy_node *create_dummy_node(uint16 n) { + + dummy_node *node = new dummy_node(); + dict_table_t *table = + dict_mem_table_create("LOG_DUMMY", DICT_HDR_SPACE, n, 0, 0, 1, 0); + dict_index_t *index = + dict_mem_index_create("LOG_DUMMY", "LOG_DUMMY", DICT_HDR_SPACE, 0, n); + index->table = table; + node->n = n; + node->index = index; + node->reuse = false; + + return node; +} + +dummy_node *get_dummy_node(uint16_t n) { + dummy_node *node; + + + auto it = dummy_node_map.find(n); + + // if no available node, malloc one and return + if (it == dummy_node_map.end()) { + dummy_node_map[n] = std::list(); + node = create_dummy_node(n); + } else { + if (it->second.empty()) { + node = create_dummy_node(n); + } else { // if found node, get it and return + node = it->second.front(); + auto it2 = it->second.begin(); + it->second.erase(it2++); + } + + } + + return node; +} + + +void restore_dummy_node(dummy_node *node) { + node->index->n_def = 0; + node->index->n_nullable = 0; + node->index->table->n_def = 0; + node->index->table->n_t_def = 0; + node->reuse = true; + + dummy_node_map[node->n].push_back(node); +} + +void clear_dummy_nodes() { + dict_table_t *table; + for (auto &it : dummy_node_map) { + for (auto& li : it.second) { + table = li->index->table; + dict_mem_index_free(li->index); + dict_mem_table_free(table); + delete li; + } + } + dummy_node_map.clear(); +} + /** Try to parse a single log record body and also applies it if specified. @param[in] type redo log entry type @@ -3521,6 +3591,7 @@ static byte *recv_parse_or_apply_log_rec_body( page_t *page; page_zip_des_t *page_zip; dict_index_t *index = nullptr; + dummy_node *node = nullptr; #ifdef UNIV_DEBUG ulint page_type; @@ -3803,7 +3874,7 @@ static byte *recv_parse_or_apply_log_rec_body( if (nullptr != (ptr = mlog_parse_index(ptr, end_ptr, type == MLOG_COMP_REC_INSERT, - &index))) { + &index, &node))) { ut_a(!page || (ibool) !!page_is_comp(page) == dict_table_is_comp(index->table)); @@ -3819,7 +3890,7 @@ static byte *recv_parse_or_apply_log_rec_body( if (nullptr != (ptr = mlog_parse_index( ptr, end_ptr, type == MLOG_COMP_REC_CLUST_DELETE_MARK, - &index))) { + &index, &node))) { ut_a(!page || (ibool) !!page_is_comp(page) == dict_table_is_comp(index->table)); @@ -3839,7 +3910,7 @@ static byte *recv_parse_or_apply_log_rec_body( ut_a(!page || page_is_comp(page)); ut_a(!page_zip); - ptr = mlog_parse_index(ptr, end_ptr, true, &index); + ptr = mlog_parse_index(ptr, end_ptr, true, &index, &node); if (ptr == nullptr) { break; @@ -3861,7 +3932,8 @@ static byte *recv_parse_or_apply_log_rec_body( if (nullptr != (ptr = mlog_parse_index( - ptr, end_ptr, type == MLOG_COMP_REC_UPDATE_IN_PLACE, &index))) { + ptr, end_ptr, type == MLOG_COMP_REC_UPDATE_IN_PLACE, + &index, &node))) { ut_a(!page || (ibool) !!page_is_comp(page) == dict_table_is_comp(index->table)); @@ -3882,7 +3954,7 @@ static byte *recv_parse_or_apply_log_rec_body( (ptr = mlog_parse_index(ptr, end_ptr, type == MLOG_COMP_LIST_END_DELETE || type == MLOG_COMP_LIST_START_DELETE, - &index))) { + &index, &node))) { ut_a(!page || (ibool) !!page_is_comp(page) == dict_table_is_comp(index->table)); @@ -3898,7 +3970,7 @@ static byte *recv_parse_or_apply_log_rec_body( if (nullptr != (ptr = mlog_parse_index( ptr, end_ptr, type == MLOG_COMP_LIST_END_COPY_CREATED, - &index))) { + &index, &node))) { ut_a(!page || (ibool) !!page_is_comp(page) == dict_table_is_comp(index->table)); @@ -3916,7 +3988,7 @@ static byte *recv_parse_or_apply_log_rec_body( if (nullptr != (ptr = mlog_parse_index(ptr, end_ptr, type != MLOG_PAGE_REORGANIZE, - &index))) { + &index, &node))) { ut_a(!page || (ibool) !!page_is_comp(page) == dict_table_is_comp(index->table)); @@ -4007,7 +4079,7 @@ static byte *recv_parse_or_apply_log_rec_body( if (nullptr != (ptr = mlog_parse_index(ptr, end_ptr, type == MLOG_COMP_REC_DELETE, - &index))) { + &index, &node))) { ut_a(!page || (ibool) !!page_is_comp(page) == dict_table_is_comp(index->table)); @@ -4073,7 +4145,8 @@ static byte *recv_parse_or_apply_log_rec_body( case MLOG_ZIP_PAGE_COMPRESS_NO_DATA: - if (nullptr != (ptr = mlog_parse_index(ptr, end_ptr, true, &index))) { + if (nullptr != + (ptr = mlog_parse_index(ptr, end_ptr, true, &index, &node))) { ut_a(!page || ((ibool) !!page_is_comp(page) == dict_table_is_comp(index->table))); @@ -4109,11 +4182,9 @@ static byte *recv_parse_or_apply_log_rec_body( << "found_corrupt_log, type:" << type << __FILE__ << " " << __LINE__; } - if (index != nullptr) { - dict_table_t *table = index->table; - dict_mem_index_free(index); - dict_mem_table_free(table); + if (index != nullptr && node != nullptr) { + restore_dummy_node(node); } return (ptr); diff --git a/mysql-8.0.19/storage/innobase/mtr/mtr0log.cc b/mysql-8.0.19/storage/innobase/mtr/mtr0log.cc index f3169acf8..dd80f38ce 100644 --- a/mysql-8.0.19/storage/innobase/mtr/mtr0log.cc +++ b/mysql-8.0.19/storage/innobase/mtr/mtr0log.cc @@ -876,7 +876,8 @@ byte *mlog_open_and_write_index( byte *mlog_parse_index(byte *ptr, /*!< in: buffer */ const byte *end_ptr, /*!< in: buffer end */ ibool comp, /*!< in: TRUE=compact row format */ - dict_index_t **index) /*!< out, own: dummy index */ + dict_index_t **index, /*!< out, own: dummy index */ + dummy_node **node) /*!< out, save node information*/ { ulint i; dict_table_t *table; @@ -916,14 +917,19 @@ byte *mlog_parse_index(byte *ptr, /*!< in: buffer */ } else { n = n_uniq = 1; } - table = dict_mem_table_create("LOG_DUMMY", DICT_HDR_SPACE, n, 0, 0, - comp ? DICT_TF_COMPACT : 0, 0); + + *node = get_dummy_node(n); + ind = (*node)->index; + table = (*node)->index->table; + table->flags = (unsigned int)(comp ? DICT_TF_COMPACT : 0); + if(DICT_TF_HAS_SHARED_SPACE(table->flags)) { + dict_get_and_save_space_name(table, true); + } + if (instant) { table->set_instant_cols(instant_cols); } - ind = dict_mem_index_create("LOG_DUMMY", "LOG_DUMMY", DICT_HDR_SPACE, 0, n); - ind->table = table; ind->n_uniq = (unsigned int)n_uniq; if (n_uniq != n) { ut_a(n_uniq + DATA_ROLL_PTR <= n); @@ -946,7 +952,13 @@ byte *mlog_parse_index(byte *ptr, /*!< in: buffer */ "less than" or "greater than". */ dict_index_add_col(ind, table, table->get_col(i), 0, true); } - dict_table_add_system_columns(table, table->heap); + if ((*node)->reuse) { + table->n_def += DATA_N_SYS_COLS; + table->n_t_def += DATA_N_SYS_COLS; + } else { + dict_table_add_system_columns(table, table->heap); + } + if (n_uniq != n) { /* Identify DB_TRX_ID and DB_ROLL_PTR in the index. */ ut_a(DATA_TRX_ID_LEN == ind->get_col(DATA_TRX_ID - 1 + n_uniq)->len);