Skip to content

Commit 906f7fa

Browse files
author
Aditya A
committed
Bug #25080442 PARTITIONED TABLES USE MORE MEMORY IN 5.7 THAN 5.6
Additional features in innodb have added new variables in memory structures which increases the total memory usage. In dict_index_t in-memory structure which is allocated for each index these three additional members are added in mysql-5.7. last_ops_cur_t* last_ins_cur :- cache the last insert position. last_ops_cur_t* last_sel_cur :- cache the last selected position rec_cache_t rec_cache :- cache the field that needs to be re-computed on each insert. These three caches are only used for temporary or intrinsic tables but memory for them is allocated for all tables which increases the overall usage of memory Fix --- This fix optimizes the memory usage by allocating memory for these caches only when they are used .
1 parent 0996bb6 commit 906f7fa

File tree

9 files changed

+82
-46
lines changed

9 files changed

+82
-46
lines changed

storage/innobase/handler/ha_innodb.cc

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8470,7 +8470,9 @@ ha_innobase::index_end(void)
84708470
{
84718471
DBUG_ENTER("index_end");
84728472

8473-
m_prebuilt->index->last_sel_cur->release();
8473+
if(m_prebuilt->index->last_sel_cur) {
8474+
m_prebuilt->index->last_sel_cur->release();
8475+
}
84748476

84758477
active_index = MAX_KEY;
84768478

@@ -12442,8 +12444,11 @@ ha_innobase::delete_table(
1244212444

1244312445
if (handler != NULL) {
1244412446
for (dict_index_t* index = UT_LIST_GET_FIRST(handler->indexes);
12445-
index != NULL;
12447+
index != NULL && index->last_ins_cur;
1244612448
index = UT_LIST_GET_NEXT(indexes, index)) {
12449+
/* last_ins_cur and last_sel_cur are allocated
12450+
together ,therfore checking only last_ins_cur
12451+
before releasing mtr */
1244712452
index->last_ins_cur->release();
1244812453
index->last_sel_cur->release();
1244912454
}

storage/innobase/include/dict0dict.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*****************************************************************************
22
3-
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
3+
Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved.
44
Copyright (c) 2012, Facebook Inc.
55
66
This program is free software; you can redistribute it and/or modify it under
@@ -2109,6 +2109,13 @@ bool
21092109
dict_table_have_virtual_index(
21102110
dict_table_t* table);
21112111

2112+
/** Allocate memory for intrinsic cache elements in the index
2113+
* @param[in] index index object */
2114+
UNIV_INLINE
2115+
void
2116+
dict_allocate_mem_intrinsic_cache(
2117+
dict_index_t* index);
2118+
21122119
#endif /* !UNIV_HOTBACKUP */
21132120

21142121
#ifndef UNIV_NONINL

storage/innobase/include/dict0dict.ic

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*****************************************************************************
22

3-
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
3+
Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved.
44

55
This program is free software; you can redistribute it and/or modify it under
66
the terms of the GNU General Public License as published by the Free Software
@@ -1938,5 +1938,25 @@ dict_table_have_virtual_index(
19381938

19391939
return(false);
19401940
}
1941+
/** Allocate memory for intrinsic cache elements in the index
1942+
@param[in] index index object */
1943+
UNIV_INLINE
1944+
void
1945+
dict_allocate_mem_intrinsic_cache(
1946+
dict_index_t* index)
1947+
{
1948+
1949+
index->last_ins_cur =
1950+
static_cast<last_ops_cur_t*>(mem_heap_alloc(
1951+
index->heap, sizeof(last_ops_cur_t)));
1952+
1953+
new (index->last_ins_cur) last_ops_cur_t();
1954+
1955+
index->last_sel_cur =
1956+
static_cast<last_ops_cur_t*>(mem_heap_alloc(
1957+
index->heap, sizeof(last_ops_cur_t)));
1958+
1959+
new (index->last_sel_cur) last_ops_cur_t();
1960+
}
19411961

19421962
#endif /* !UNIV_HOTBACKUP */

storage/innobase/include/dict0mem.h

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*****************************************************************************
22
3-
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
3+
Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved.
44
Copyright (c) 2012, Facebook Inc.
55
66
This program is free software; you can redistribute it and/or modify it under
@@ -850,10 +850,6 @@ class last_ops_cur_t
850850
system clustered index when there is no primary key. */
851851
const char innobase_index_reserve_name[] = "GEN_CLUST_INDEX";
852852

853-
/* Estimated number of offsets in records (based on columns)
854-
to start with. */
855-
#define OFFS_IN_REC_NORMAL_SIZE 100
856-
857853
/** Data structure for an index. Most fields will be
858854
initialized to 0, NULL or FALSE in dict_mem_index_create(). */
859855
struct dict_index_t{

storage/innobase/include/dict0mem.ic

Lines changed: 3 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*****************************************************************************
22

3-
Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved.
3+
Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved.
44

55
This program is free software; you can redistribute it and/or modify it under
66
the terms of the GNU General Public License as published by the Free Software
@@ -72,33 +72,10 @@ dict_mem_fill_index_struct(
7272
index->allow_duplicates = false;
7373
index->nulls_equal = false;
7474
index->disable_ahi = false;
75-
75+
index->last_ins_cur = NULL;
76+
index->last_sel_cur = NULL;
7677
new (&index->rec_cache) rec_cache_t();
7778

78-
if (heap != NULL) {
79-
index->last_ins_cur =
80-
static_cast<last_ops_cur_t*>(mem_heap_alloc(
81-
heap, sizeof(last_ops_cur_t)));
82-
83-
new (index->last_ins_cur) last_ops_cur_t();
84-
85-
index->last_sel_cur =
86-
static_cast<last_ops_cur_t*>(mem_heap_alloc(
87-
heap, sizeof(last_ops_cur_t)));
88-
89-
new (index->last_sel_cur) last_ops_cur_t();
90-
91-
index->rec_cache.offsets =
92-
static_cast<ulint*>(mem_heap_alloc(
93-
heap, sizeof(ulint) * OFFS_IN_REC_NORMAL_SIZE));
94-
95-
index->rec_cache.sz_of_offsets = OFFS_IN_REC_NORMAL_SIZE;
96-
} else {
97-
index->last_ins_cur = NULL;
98-
index->last_sel_cur = NULL;
99-
index->rec_cache.offsets = NULL;
100-
}
101-
10279
#ifdef UNIV_DEBUG
10380
index->magic_n = DICT_INDEX_MAGIC_N;
10481
#endif /* UNIV_DEBUG */

storage/innobase/include/rem0rec.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*****************************************************************************
22
3-
Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved.
3+
Copyright (c) 1994, 2017, Oracle and/or its affiliates. All Rights Reserved.
44
55
This program is free software; you can redistribute it and/or modify it under
66
the terms of the GNU General Public License as published by the Free Software
@@ -88,7 +88,7 @@ significant bit denotes that the tail of a field is stored off-page. */
8888

8989
/* Number of elements that should be initially allocated for the
9090
offsets[] array, first passed to rec_get_offsets() */
91-
#define REC_OFFS_NORMAL_SIZE OFFS_IN_REC_NORMAL_SIZE
91+
#define REC_OFFS_NORMAL_SIZE 100
9292
#define REC_OFFS_SMALL_SIZE 10
9393

9494
/******************************************************//**

storage/innobase/row/row0ins.cc

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*****************************************************************************
22
3-
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
3+
Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved.
44
55
This program is free software; you can redistribute it and/or modify it under
66
the terms of the GNU General Public License as published by the Free Software
@@ -2579,7 +2579,9 @@ row_ins_clust_index_entry_low(
25792579
doesn't fit the provided slot then existing record is added
25802580
to free list and new record is inserted. This also means
25812581
cursor that we have cached for SELECT is now invalid. */
2582-
index->last_sel_cur->invalid = true;
2582+
if(index->last_sel_cur) {
2583+
index->last_sel_cur->invalid = true;
2584+
}
25832585

25842586
err = row_ins_clust_index_entry_by_modify(
25852587
&pcur, flags, mode, &offsets, &offsets_heap,
@@ -3132,7 +3134,9 @@ row_ins_sec_index_entry_low(
31323134
is doesn't fit the provided slot then existing record is added
31333135
to free list and new record is inserted. This also means
31343136
cursor that we have cached for SELECT is now invalid. */
3135-
index->last_sel_cur->invalid = true;
3137+
if(index->last_sel_cur) {
3138+
index->last_sel_cur->invalid = true;
3139+
}
31363140

31373141
/* There is already an index entry with a long enough common
31383142
prefix, we must convert the insert into a modify of an
@@ -3311,6 +3315,12 @@ row_ins_clust_index_entry(
33113315

33123316
if (dict_table_is_intrinsic(index->table)
33133317
&& dict_index_is_auto_gen_clust(index)) {
3318+
3319+
/* Check if the memory allocated for intrinsic cache*/
3320+
if(!index->last_ins_cur) {
3321+
dict_allocate_mem_intrinsic_cache(index);
3322+
}
3323+
33143324
err = row_ins_sorted_clust_index_entry(
33153325
BTR_MODIFY_LEAF, index, entry, n_ext, thr);
33163326
} else {
@@ -3331,6 +3341,9 @@ row_ins_clust_index_entry(
33313341
/* Try then pessimistic descent to the B-tree */
33323342
if (!dict_table_is_intrinsic(index->table)) {
33333343
log_free_check();
3344+
} else if(!index->last_sel_cur) {
3345+
dict_allocate_mem_intrinsic_cache(index);
3346+
index->last_sel_cur->invalid = true;
33343347
} else {
33353348
index->last_sel_cur->invalid = true;
33363349
}
@@ -3410,6 +3423,9 @@ row_ins_sec_index_entry(
34103423

34113424
if (!dict_table_is_intrinsic(index->table)) {
34123425
log_free_check();
3426+
} else if(!index->last_sel_cur) {
3427+
dict_allocate_mem_intrinsic_cache(index);
3428+
index->last_sel_cur->invalid = true;
34133429
} else {
34143430
index->last_sel_cur->invalid = true;
34153431
}

storage/innobase/row/row0mysql.cc

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2285,7 +2285,9 @@ row_update_for_mysql_using_cursor(
22852285
node->upd_ext ? node->upd_ext->n_ext : 0,
22862286
false);
22872287
/* Commit the open mtr as we are processing UPDATE. */
2288-
index->last_ins_cur->release();
2288+
if (index->last_ins_cur) {
2289+
index->last_ins_cur->release();
2290+
}
22892291
} else {
22902292
err = row_ins_sec_index_entry(index, entry, thr, false);
22912293
}
@@ -2329,7 +2331,9 @@ row_del_upd_for_mysql_using_cursor(
23292331
to change. */
23302332
thr = que_fork_get_first_thr(prebuilt->upd_graph);
23312333
clust_index = dict_table_get_first_index(prebuilt->table);
2332-
clust_index->last_ins_cur->release();
2334+
if (clust_index->last_ins_cur) {
2335+
clust_index->last_ins_cur->release();
2336+
}
23332337

23342338
/* Step-1: Select the appropriate cursor that will help build
23352339
the original row and updated row. */
@@ -2731,15 +2735,20 @@ row_delete_all_rows(
27312735
dict_table_t* table)
27322736
{
27332737
dberr_t err = DB_SUCCESS;
2738+
dict_index_t* index;
2739+
27342740

2741+
index = dict_table_get_first_index(table);
27352742
/* Step-0: If there is cached insert position along with mtr
27362743
commit it before starting delete/update action. */
2737-
dict_table_get_first_index(table)->last_ins_cur->release();
2744+
if (index->last_ins_cur) {
2745+
index->last_ins_cur->release();
2746+
}
27382747

27392748
/* Step-1: Now truncate all the indexes and re-create them.
27402749
Note: This is ddl action even though delete all rows is
27412750
DML action. Any error during this action is ir-reversible. */
2742-
for (dict_index_t* index = UT_LIST_GET_FIRST(table->indexes);
2751+
for (index = UT_LIST_GET_FIRST(table->indexes);
27432752
index != NULL && err == DB_SUCCESS;
27442753
index = UT_LIST_GET_NEXT(indexes, index)) {
27452754

storage/innobase/row/row0sel.cc

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*****************************************************************************
22
3-
Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved.
3+
Copyright (c) 1997, 2017, Oracle and/or its affiliates. All Rights Reserved.
44
Copyright (c) 2008, Google Inc.
55
66
Portions of this file contain modifications contributed and copyrighted by
@@ -4257,9 +4257,15 @@ row_search_no_mvcc(
42574257
ut_ad(index && pcur && search_tuple);
42584258

42594259
/* Step-0: Re-use the cached mtr. */
4260-
mtr_t* mtr = &index->last_sel_cur->mtr;
4260+
mtr_t* mtr;
42614261
dict_index_t* clust_index = dict_table_get_first_index(index->table);
42624262

4263+
if(!index->last_sel_cur) {
4264+
dict_allocate_mem_intrinsic_cache(index);
4265+
}
4266+
4267+
mtr = &index->last_sel_cur->mtr;
4268+
42634269
/* Step-1: Build the select graph. */
42644270
if (direction == 0 && prebuilt->sel_graph == NULL) {
42654271
row_prebuild_sel_graph(prebuilt);

0 commit comments

Comments
 (0)