Skip to content

Commit 450ca04

Browse files
committed
Bug#36220640 Mrr implement runs much slower than before
Queries using the Multi-Range Read optimization run slower after the fix for Bug#36017204. The reason is that the insertion sort used to sort the records in the MRR buffer does not perform well when the number of records in the buffer is high. Fixed by replacing the insertion sort with a call to qsort() in the C standard library. It performs better on large buffers. Change-Id: I39da5db5c329d482bf83b18fb27e52a0c5fcae03
1 parent 734a43a commit 450ca04

File tree

6 files changed

+45
-288
lines changed

6 files changed

+45
-288
lines changed

include/varlen_sort.h

-197
This file was deleted.

sql/handler.cc

+12-4
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,6 @@
131131
#include "string_with_len.h"
132132
#include "template_utils.h"
133133
#include "uniques.h" // Unique_on_insert
134-
#include "varlen_sort.h"
135134

136135
/**
137136
@def MYSQL_TABLE_IO_WAIT
@@ -6853,9 +6852,18 @@ int DsMrr_impl::dsmrr_fill_buffer() {
68536852
const uint elem_size = h->ref_length + (int)is_mrr_assoc * sizeof(void *);
68546853
assert((rowids_buf_cur - rowids_buf) % elem_size == 0);
68556854

6856-
varlen_sort(
6857-
rowids_buf, rowids_buf_cur, elem_size,
6858-
[this](const uchar *a, const uchar *b) { return h->cmp_ref(a, b) < 0; });
6855+
// Store the handler in a thread local variable so that it is available in the
6856+
// stateless comparator passed to qsort.
6857+
thread_local const handler *current_handler;
6858+
current_handler = h;
6859+
6860+
qsort(rowids_buf, (rowids_buf_cur - rowids_buf) / elem_size, elem_size,
6861+
[](const void *a, const void *b) {
6862+
return current_handler->cmp_ref(
6863+
static_cast<const unsigned char *>(a),
6864+
static_cast<const unsigned char *>(b));
6865+
});
6866+
68596867
rowids_buf_last = rowids_buf_cur;
68606868
rowids_buf_cur = rowids_buf;
68616869
return 0;

sql/iterators/sorting_iterator.cc

-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@
6060
#include "sql/system_variables.h"
6161
#include "sql/table.h"
6262
#include "thr_lock.h"
63-
#include "varlen_sort.h"
6463

6564
using std::string;
6665
using std::vector;

sql/partition_info.cc

+33-25
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
#include <limits.h>
2626
#include <stdio.h>
27+
#include <stdlib.h>
2728
#include <string.h>
2829

2930
#include <algorithm>
@@ -68,7 +69,6 @@
6869
#include "sql/trigger_def.h"
6970
#include "sql_string.h"
7071
#include "string_with_len.h"
71-
#include "varlen_sort.h"
7272

7373
using std::string;
7474

@@ -1176,45 +1176,50 @@ bool partition_info::check_range_constants(THD *thd) {
11761176
goto end;
11771177
}
11781178

1179-
/*
1180-
Compare two lists of column values in RANGE/LIST partitioning
1181-
SYNOPSIS
1182-
compare_column_values()
1183-
first First column list argument
1184-
second Second column list argument
1185-
RETURN VALUES
1186-
true first < second
1187-
false first >= second
1188-
*/
1189-
1190-
static bool partition_info_compare_column_values(
1179+
static int partition_info_compare_column_values(
11911180
const part_column_list_val *first, const part_column_list_val *second) {
11921181
for (Field **field = first->part_info->part_field_array; *field;
11931182
field++, first++, second++) {
11941183
/*
11951184
If both are maxvalue, they are equal (don't check the rest of the parts).
11961185
Otherwise, maxvalue > *.
1197-
*/
1198-
if (first->max_value || second->max_value)
1199-
return first->max_value < second->max_value;
1186+
*/
1187+
if (first->max_value) {
1188+
return second->max_value ? 0 : 1;
1189+
} else if (second->max_value) {
1190+
return -1;
1191+
}
12001192

12011193
// NULLs sort before non-NULLs.
1202-
if (first->null_value != second->null_value) return first->null_value;
1194+
if (first->null_value != second->null_value) {
1195+
return first->null_value ? -1 : 1;
1196+
}
12031197

12041198
// For non-NULLs, compare the actual fields.
12051199
if (!first->null_value) {
12061200
int res = (*field)->cmp(first->column_value.field_image,
12071201
second->column_value.field_image);
1208-
if (res != 0) return res < 0;
1202+
if (res != 0) return res;
12091203
}
12101204
}
1211-
return false;
1205+
return 0;
12121206
}
12131207

1208+
/*
1209+
Compare two lists of column values in RANGE/LIST partitioning
1210+
SYNOPSIS
1211+
compare_column_values()
1212+
first First column list argument
1213+
second Second column list argument
1214+
RETURN VALUES
1215+
true first < second
1216+
false first >= second
1217+
*/
1218+
12141219
bool partition_info::compare_column_values(
12151220
const part_column_list_val *first_arg,
12161221
const part_column_list_val *second_arg) {
1217-
return partition_info_compare_column_values(first_arg, second_arg);
1222+
return partition_info_compare_column_values(first_arg, second_arg) < 0;
12181223
}
12191224

12201225
/*
@@ -1309,14 +1314,17 @@ bool partition_info::check_list_constants(THD *thd) {
13091314
}
13101315
} while (++part_id < num_parts);
13111316

1312-
varlen_sort(list_col_array,
1313-
list_col_array + num_list_values * num_column_values,
1314-
size_entries, partition_info_compare_column_values);
1317+
qsort(list_col_array, num_list_values, size_entries,
1318+
[](const void *a, const void *b) {
1319+
return partition_info_compare_column_values(
1320+
static_cast<const part_column_list_val *>(a),
1321+
static_cast<const part_column_list_val *>(b));
1322+
});
13151323

13161324
for (uint i = 1; i < num_list_values; ++i) {
1317-
if (!partition_info_compare_column_values(
1325+
if (partition_info_compare_column_values(
13181326
&list_col_array[num_column_values * (i - 1)],
1319-
&list_col_array[num_column_values * i])) {
1327+
&list_col_array[num_column_values * i]) >= 0) {
13201328
my_error(ER_MULTIPLE_DEF_CONST_IN_LIST_PART_ERROR, MYF(0));
13211329
goto end;
13221330
}

unittest/gunit/CMakeLists.txt

-1
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,6 @@ SET(TESTS
181181
timespec
182182
unhex
183183
val_int_compare
184-
varlen_sort
185184
)
186185

187186
SET(ALL_SMALL_TESTS)

0 commit comments

Comments
 (0)