Skip to content

Commit f112fed

Browse files
author
Aditya A
committed
Bug #17780517 5.6 PARTITIONS USE MUCH MORE MEMORY THAN 5.1
[ Merge from 5.6 ]
2 parents 3ae9bc8 + 3e2de58 commit f112fed

File tree

5 files changed

+72
-21
lines changed

5 files changed

+72
-21
lines changed

storage/innobase/handler/ha_innodb.cc

+6-3
Original file line numberDiff line numberDiff line change
@@ -7507,7 +7507,8 @@ ha_innobase::index_read(
75077507

75087508
row_sel_convert_mysql_key_to_innobase(
75097509
prebuilt->search_tuple,
7510-
srch_key_val1, sizeof(srch_key_val1),
7510+
prebuilt->srch_key_val1,
7511+
prebuilt->srch_key_val_len,
75117512
index,
75127513
(byte*) key_ptr,
75137514
(ulint) key_len,
@@ -10881,7 +10882,8 @@ ha_innobase::records_in_range(
1088110882

1088210883
row_sel_convert_mysql_key_to_innobase(
1088310884
range_start,
10884-
srch_key_val1, sizeof(srch_key_val1),
10885+
prebuilt->srch_key_val1,
10886+
prebuilt->srch_key_val_len,
1088510887
index,
1088610888
(byte*) (min_key ? min_key->key :
1088710889
(const uchar*) 0),
@@ -10893,7 +10895,8 @@ ha_innobase::records_in_range(
1089310895

1089410896
row_sel_convert_mysql_key_to_innobase(
1089510897
range_end,
10896-
srch_key_val2, sizeof(srch_key_val2),
10898+
prebuilt->srch_key_val2,
10899+
prebuilt->srch_key_val_len,
1089710900
index,
1089810901
(byte*) (max_key ? max_key->key :
1089910902
(const uchar*) 0),

storage/innobase/handler/ha_innodb.h

-7
Original file line numberDiff line numberDiff line change
@@ -72,13 +72,6 @@ class ha_innobase: public handler
7272

7373
uchar* upd_buf; /*!< buffer used in updates */
7474
ulint upd_buf_size; /*!< the size of upd_buf in bytes */
75-
uchar srch_key_val1[MAX_KEY_LENGTH + MAX_REF_PARTS*2];
76-
uchar srch_key_val2[MAX_KEY_LENGTH + MAX_REF_PARTS*2];
77-
/*!< buffers used in converting
78-
search key values from MySQL format
79-
to InnoDB format. For each column
80-
2 bytes are used to store length,
81-
hence MAX_REF_PARTS*2. */
8275
Table_flags int_table_flags;
8376
uint primary_key;
8477
ulong start_of_scan; /*!< this is set to 1 when we are

storage/innobase/include/row0mysql.h

+8
Original file line numberDiff line numberDiff line change
@@ -912,6 +912,14 @@ struct row_prebuilt_t {
912912

913913
innodb_session_t*
914914
session; /*!< InnoDB session handler. */
915+
byte* srch_key_val1; /*!< buffer used in converting
916+
search key values from MySQL format
917+
to InnoDB format.*/
918+
byte* srch_key_val2; /*!< buffer used in converting
919+
search key values from MySQL format
920+
to InnoDB format.*/
921+
uint srch_key_val_len; /*!< Size of search key */
922+
915923
};
916924

917925
/** Callback for row_mysql_sys_index_iterate() */

storage/innobase/row/row0mysql.cc

+52-1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ Created 9/17/2000 Heikki Tuuri
3838
#include "btr0sea.h"
3939
#include "dict0boot.h"
4040
#include "dict0crea.h"
41+
#include <sql_const.h>
4142
#include "dict0dict.h"
4243
#include "dict0load.h"
4344
#include "dict0stats.h"
@@ -804,8 +805,10 @@ row_create_prebuilt(
804805
row_prebuilt_t* prebuilt;
805806
mem_heap_t* heap;
806807
dict_index_t* clust_index;
808+
dict_index_t* temp_index;
807809
dtuple_t* ref;
808810
ulint ref_len;
811+
uint srch_key_len = 0;
809812
ulint search_tuple_n_fields;
810813

811814
search_tuple_n_fields = 2 * dict_table_get_n_cols(table);
@@ -817,6 +820,14 @@ row_create_prebuilt(
817820

818821
ref_len = dict_index_get_n_unique(clust_index);
819822

823+
824+
/* Maximum size of the buffer needed for conversion of INTs from
825+
little endian format to big endian format in an index. An index
826+
can have maximum 16 columns (MAX_REF_PARTS) in it. Therfore
827+
Max size for PK: 16 * 8 bytes (BIGINT's size) = 128 bytes
828+
Max size Secondary index: 16 * 8 bytes + PK = 256 bytes. */
829+
#define MAX_SRCH_KEY_VAL_BUFFER 2* (8 * MAX_REF_PARTS)
830+
820831
#define PREBUILT_HEAP_INITIAL_SIZE \
821832
( \
822833
sizeof(*prebuilt) \
@@ -845,10 +856,38 @@ row_create_prebuilt(
845856
+ sizeof(que_thr_t) \
846857
)
847858

859+
/* Calculate size of key buffer used to store search key in
860+
InnoDB format. MySQL stores INTs in little endian format and
861+
InnoDB stores INTs in big endian format with the sign bit
862+
flipped. All other field types are stored/compared the same
863+
in MySQL and InnoDB, so we must create a buffer containing
864+
the INT key parts in InnoDB format.We need two such buffers
865+
since both start and end keys are used in records_in_range(). */
866+
867+
for (temp_index = dict_table_get_first_index(table); temp_index;
868+
temp_index = dict_table_get_next_index(temp_index)) {
869+
DBUG_EXECUTE_IF("innodb_srch_key_buffer_max_value",
870+
ut_a(temp_index->n_user_defined_cols
871+
== MAX_REF_PARTS););
872+
uint temp_len = 0;
873+
for (int i = 0; i < temp_index->n_uniq; i++) {
874+
if (temp_index->fields[i].col->mtype == DATA_INT) {
875+
temp_len +=
876+
temp_index->fields[i].fixed_len;
877+
}
878+
}
879+
srch_key_len = std::max(srch_key_len,temp_len);
880+
}
881+
882+
ut_a(srch_key_len <= MAX_SRCH_KEY_VAL_BUFFER);
883+
884+
DBUG_EXECUTE_IF("innodb_srch_key_buffer_max_value",
885+
ut_a(srch_key_len == MAX_SRCH_KEY_VAL_BUFFER););
886+
848887
/* We allocate enough space for the objects that are likely to
849888
be created later in order to minimize the number of malloc()
850889
calls */
851-
heap = mem_heap_create(PREBUILT_HEAP_INITIAL_SIZE);
890+
heap = mem_heap_create(PREBUILT_HEAP_INITIAL_SIZE + 2 * srch_key_len);
852891

853892
prebuilt = static_cast<row_prebuilt_t*>(
854893
mem_heap_zalloc(heap, sizeof(*prebuilt)));
@@ -861,6 +900,18 @@ row_create_prebuilt(
861900
prebuilt->sql_stat_start = TRUE;
862901
prebuilt->heap = heap;
863902

903+
prebuilt->srch_key_val_len = srch_key_len;
904+
if (prebuilt->srch_key_val_len) {
905+
prebuilt->srch_key_val1 = static_cast<byte*>(
906+
mem_heap_alloc(prebuilt->heap,
907+
2 * prebuilt->srch_key_val_len));
908+
prebuilt->srch_key_val2 = prebuilt->srch_key_val1 +
909+
prebuilt->srch_key_val_len;
910+
} else {
911+
prebuilt->srch_key_val1 = NULL;
912+
prebuilt->srch_key_val2 = NULL;
913+
}
914+
864915
btr_pcur_reset(&prebuilt->pcur);
865916
btr_pcur_reset(&prebuilt->clust_pcur);
866917

storage/innobase/row/row0sel.cc

+6-10
Original file line numberDiff line numberDiff line change
@@ -2696,13 +2696,12 @@ row_sel_convert_mysql_key_to_innobase(
26962696
/* Storing may use at most data_len bytes of buf */
26972697

26982698
if (UNIV_LIKELY(!is_null)) {
2699-
ut_a(buf + data_len <= original_buf + buf_len);
2700-
row_mysql_store_col_in_innobase_format(
2701-
dfield, buf,
2702-
FALSE, /* MySQL key value format col */
2703-
key_ptr + data_offset, data_len,
2704-
dict_table_is_comp(index->table));
2705-
buf += data_len;
2699+
buf = row_mysql_store_col_in_innobase_format(
2700+
dfield, buf,
2701+
FALSE, /* MySQL key value format col */
2702+
key_ptr + data_offset, data_len,
2703+
dict_table_is_comp(index->table));
2704+
ut_a(buf <= original_buf + buf_len);
27062705
}
27072706

27082707
key_ptr += data_field_len;
@@ -2742,9 +2741,6 @@ row_sel_convert_mysql_key_to_innobase(
27422741
dfield++;
27432742
}
27442743

2745-
DBUG_EXECUTE_IF("innodb_srch_key_buffer_full",
2746-
ut_a(buf == (original_buf + buf_len)););
2747-
27482744
ut_a(buf <= original_buf + buf_len);
27492745

27502746
/* We set the length of tuple to n_fields: we assume that the memory

0 commit comments

Comments
 (0)