From 45973ec61058b1428ae88316631f49e58d227207 Mon Sep 17 00:00:00 2001 From: Eugene Kosov Date: Thu, 19 Mar 2020 18:33:19 +0300 Subject: InnoDB: reduce size of dtuple_t Making a linked list of dtuple_t is needed only for inserting records. It's better to store tuples in a non-intrusive container to not affect all other use cases of dtuple_t dtuple_t::tuple_list: removed, it was 2 * sizeof(void*) bytes ins_node_t::entry_list: now it's std::vector ins_node_t::entry: now it's std::vector::iterator DBUG_EXECUTE_IF("row_ins_skip_sec": this dead code removed --- storage/innobase/include/data0data.h | 6 ++---- storage/innobase/include/row0ins.h | 15 +++++++++----- storage/innobase/que/que0que.cc | 4 +++- storage/innobase/row/row0ins.cc | 38 +++++++++++++++++------------------- storage/innobase/row/row0mysql.cc | 2 +- 5 files changed, 34 insertions(+), 31 deletions(-) diff --git a/storage/innobase/include/data0data.h b/storage/innobase/include/data0data.h index 33d03c8a2c9..fdf1a14feee 100644 --- a/storage/innobase/include/data0data.h +++ b/storage/innobase/include/data0data.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2019, MariaDB Corporation. +Copyright (c) 2017, 2019, 2020 MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -32,6 +32,7 @@ Created 5/30/1994 Heikki Tuuri #include "mem0mem.h" #include "dict0types.h" #include "btr0types.h" +#include #include @@ -510,9 +511,6 @@ struct dtuple_t { dfield_t* fields; /*!< fields */ ulint n_v_fields; /*!< number of virtual fields */ dfield_t* v_fields; /*!< fields on virtual column */ - UT_LIST_NODE_T(dtuple_t) tuple_list; - /*!< data tuples can be linked into a - list using this field */ #ifdef UNIV_DEBUG ulint magic_n; /*!< magic number, used in debug assertions */ diff --git a/storage/innobase/include/row0ins.h b/storage/innobase/include/row0ins.h index 164f6fe1ddb..27fe442f6ff 100644 --- a/storage/innobase/include/row0ins.h +++ b/storage/innobase/include/row0ins.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2019, MariaDB Corporation. +Copyright (c) 2017, 2019, 2020 MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -31,6 +31,7 @@ Created 4/20/1996 Heikki Tuuri #include "que0types.h" #include "trx0types.h" #include "row0types.h" +#include /***************************************************************//** Checks if foreign key constraint fails for an index entry. Sets shared locks @@ -159,7 +160,10 @@ row_ins_step( /* Insert node structure */ struct ins_node_t{ - que_common_t common; /*!< node type: QUE_NODE_INSERT */ + ins_node_t() : common(QUE_NODE_INSERT, NULL), entry(entry_list.end()) + { + } + que_common_t common; /*!< node type: QUE_NODE_INSERT */ ulint ins_type;/* INS_VALUES, INS_SEARCHED, or INS_DIRECT */ dtuple_t* row; /*!< row to insert */ dict_table_t* table; /*!< table where to insert */ @@ -169,11 +173,12 @@ struct ins_node_t{ ulint state; /*!< node execution state */ dict_index_t* index; /*!< NULL, or the next index where the index entry should be inserted */ - dtuple_t* entry; /*!< NULL, or entry to insert in the index; + std::vector + entry_list;/* list of entries, one for each index */ + std::vector::iterator + entry; /*!< NULL, or entry to insert in the index; after a successful insert of the entry, this should be reset to NULL */ - UT_LIST_BASE_NODE_T(dtuple_t) - entry_list;/* list of entries, one for each index */ /** buffer for the system columns */ byte sys_buf[DATA_ROW_ID_LEN + DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN]; diff --git a/storage/innobase/que/que0que.cc b/storage/innobase/que/que0que.cc index 1d3d1573299..3ad948af4d2 100644 --- a/storage/innobase/que/que0que.cc +++ b/storage/innobase/que/que0que.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2018, MariaDB Corporation. +Copyright (c) 2017, 2018, 2020 MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -460,6 +460,8 @@ que_graph_free_recursive( que_graph_free_recursive(ins->select); ins->select = NULL; + ins->~ins_node_t(); + if (ins->entry_sys_heap != NULL) { mem_heap_free(ins->entry_sys_heap); ins->entry_sys_heap = NULL; diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc index cb27d4f8dd3..c4410f15b84 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2016, 2019, MariaDB Corporation. +Copyright (c) 2016, 2019, 2020 MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -73,8 +73,8 @@ ins_node_create( { ins_node_t* node; - node = static_cast( - mem_heap_alloc(heap, sizeof(ins_node_t))); + node = new (static_cast( + mem_heap_alloc(heap, sizeof(ins_node_t)))) ins_node_t; node->common.type = QUE_NODE_INSERT; @@ -83,7 +83,6 @@ ins_node_create( node->state = INS_NODE_SET_IX_LOCK; node->table = table; node->index = NULL; - node->entry = NULL; node->select = NULL; @@ -109,12 +108,12 @@ ins_node_create_entry_list( ut_ad(node->entry_sys_heap); - UT_LIST_INIT(node->entry_list, &dtuple_t::tuple_list); - /* We will include all indexes (include those corrupted - secondary indexes) in the entry list. Filteration of + secondary indexes) in the entry list. Filtration of these corrupted index will be done in row_ins() */ + node->entry_list.reserve(UT_LIST_GET_LEN(node->table->indexes)); + for (index = dict_table_get_first_index(node->table); index != 0; index = dict_table_get_next_index(index)) { @@ -123,7 +122,7 @@ ins_node_create_entry_list( node->row, NULL, index, node->entry_sys_heap, ROW_BUILD_FOR_INSERT); - UT_LIST_ADD_LAST(node->entry_list, entry); + node->entry_list.push_back(entry); } } @@ -189,7 +188,8 @@ ins_node_set_new_row( { node->state = INS_NODE_SET_IX_LOCK; node->index = NULL; - node->entry = NULL; + node->entry_list.clear(); + node->entry = node->entry_list.end(); node->row = row; @@ -3413,15 +3413,16 @@ row_ins_index_entry_step( ut_ad(dtuple_check_typed(node->row)); - err = row_ins_index_entry_set_vals(node->index, node->entry, node->row); + err = row_ins_index_entry_set_vals(node->index, *node->entry, + node->row); if (err != DB_SUCCESS) { DBUG_RETURN(err); } - ut_ad(dtuple_check_typed(node->entry)); + ut_ad(dtuple_check_typed(*node->entry)); - err = row_ins_index_entry(node->index, node->entry, thr); + err = row_ins_index_entry(node->index, *node->entry, thr); DEBUG_SYNC_C_IF_THD(thr_get_trx(thr)->mysql_thd, "after_row_ins_index_entry_step"); @@ -3539,7 +3540,8 @@ row_ins( row_ins_alloc_row_id_step(node); node->index = dict_table_get_first_index(node->table); - node->entry = UT_LIST_GET_FIRST(node->entry_list); + ut_ad(node->entry_list.empty() == false); + node->entry = node->entry_list.begin(); if (node->ins_type == INS_SEARCHED) { @@ -3565,20 +3567,16 @@ row_ins( } node->index = dict_table_get_next_index(node->index); - node->entry = UT_LIST_GET_NEXT(tuple_list, node->entry); - - DBUG_EXECUTE_IF( - "row_ins_skip_sec", - node->index = NULL; node->entry = NULL; break;); + ++node->entry; /* Skip corrupted secondary index and its entry */ while (node->index && node->index->is_corrupted()) { node->index = dict_table_get_next_index(node->index); - node->entry = UT_LIST_GET_NEXT(tuple_list, node->entry); + ++node->entry; } } - ut_ad(node->entry == NULL); + ut_ad(node->entry == node->entry_list.end()); node->state = INS_NODE_ALLOC_ROW_ID; diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index 9add75b3a67..c708842b04d 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -1092,7 +1092,7 @@ row_get_prebuilt_insert_row( may need to rebuild the row insert template. */ if (prebuilt->trx_id == table->def_trx_id - && UT_LIST_GET_LEN(prebuilt->ins_node->entry_list) + && prebuilt->ins_node->entry_list.size() == UT_LIST_GET_LEN(table->indexes)) { return(prebuilt->ins_node->row); -- cgit v1.2.1