Skip to content

Commit 0623cc7

Browse files
Thirunarayanandr-m
authored andcommitted
MDEV-19051 Avoid unnecessary writing MLOG_INDEX_LOAD
1) Avoid writing of MLOG_INDEX_LOAD redo log record during inplace alter table when the table is empty and also for spatial index. 2) Avoid creation of temporary merge file for spatial index during index creation process.
1 parent 38cad68 commit 0623cc7

File tree

5 files changed

+84
-79
lines changed

5 files changed

+84
-79
lines changed

storage/innobase/include/btr0bulk.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/*****************************************************************************
22
33
Copyright (c) 2014, 2015, Oracle and/or its affiliates. All Rights Reserved.
4+
Copyright (c) 2019, MariaDB Corporation.
45
56
This program is free software; you can redistribute it and/or modify it under
67
the terms of the GNU General Public License as published by the Free Software
@@ -284,6 +285,7 @@ class BtrBulk
284285
m_trx(trx),
285286
m_flush_observer(observer)
286287
{
288+
ut_ad(!dict_index_is_spatial(index));
287289
#ifdef UNIV_DEBUG
288290
if (m_flush_observer)
289291
fil_space_inc_redo_skipped_count(m_index->space);

storage/innobase/include/trx0trx.h

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*****************************************************************************
22
33
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
4-
Copyright (c) 2015, 2018, MariaDB Corporation.
4+
Copyright (c) 2015, 2019, MariaDB Corporation.
55
66
This program is free software; you can redistribute it and/or modify it under
77
the terms of the GNU General Public License as published by the Free Software
@@ -40,20 +40,9 @@ Created 3/26/1996 Heikki Tuuri
4040

4141
// Forward declaration
4242
struct mtr_t;
43-
44-
// Forward declaration
4543
class ReadView;
46-
47-
// Forward declaration
4844
class FlushObserver;
49-
50-
/** Set flush observer for the transaction
51-
@param[in/out] trx transaction struct
52-
@param[in] observer flush observer */
53-
void
54-
trx_set_flush_observer(
55-
trx_t* trx,
56-
FlushObserver* observer);
45+
class ut_stage_alter_t;
5746

5847
/******************************************************************//**
5948
Set detailed error message for the transaction. */
@@ -1132,8 +1121,11 @@ struct trx_t {
11321121
/*------------------------------*/
11331122
char* detailed_error; /*!< detailed error message for last
11341123
error, or empty. */
1135-
FlushObserver* flush_observer; /*!< flush observer */
1136-
1124+
private:
1125+
/** flush observer used to track flushing of non-redo logged pages
1126+
during bulk create index */
1127+
FlushObserver* flush_observer;
1128+
public:
11371129
/* Lock wait statistics */
11381130
ulint n_rec_lock_waits;
11391131
/*!< Number of record lock waits,
@@ -1177,6 +1169,20 @@ struct trx_t {
11771169
return(assign_temp_rseg());
11781170
}
11791171

1172+
/** Set the innodb_log_optimize_ddl page flush observer
1173+
@param[in] space_id tablespace id
1174+
@param[in,out] stage performance_schema accounting */
1175+
void set_flush_observer(ulint space_id, ut_stage_alter_t* stage);
1176+
1177+
/** Remove the flush observer */
1178+
void remove_flush_observer();
1179+
1180+
/** @return the flush observer */
1181+
FlushObserver* get_flush_observer() const
1182+
{
1183+
return flush_observer;
1184+
}
1185+
11801186
private:
11811187
/** Assign a rollback segment for modifying temporary tables.
11821188
@return the assigned rollback segment */

storage/innobase/row/row0ftsort.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1673,7 +1673,7 @@ row_fts_merge_insert(
16731673
/* Create bulk load instance */
16741674
ins_ctx.btr_bulk = UT_NEW_NOKEY(
16751675
BtrBulk(aux_index, trx, psort_info[0].psort_common->trx
1676-
->flush_observer));
1676+
->get_flush_observer()));
16771677

16781678
/* Create tuple for insert */
16791679
ins_ctx.tuple = dtuple_create(heap, dict_index_get_n_fields(aux_index));

storage/innobase/row/row0merge.cc

Lines changed: 43 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1736,7 +1736,6 @@ row_merge_read_clustered_index(
17361736
mem_heap_t* mtuple_heap = NULL;
17371737
mtuple_t prev_mtuple;
17381738
mem_heap_t* conv_heap = NULL;
1739-
FlushObserver* observer = trx->flush_observer;
17401739
double curr_progress = 0.0;
17411740
ib_uint64_t read_rows = 0;
17421741
ib_uint64_t table_total_rows = 0;
@@ -2211,9 +2210,8 @@ row_merge_read_clustered_index(
22112210
bool skip_sort = skip_pk_sort
22122211
&& dict_index_is_clust(merge_buf[0]->index);
22132212

2214-
for (ulint i = 0; i < n_index; i++, skip_sort = false) {
2213+
for (ulint k = 0, i = 0; i < n_index; i++, skip_sort = false) {
22152214
row_merge_buf_t* buf = merge_buf[i];
2216-
merge_file_t* file = &files[i];
22172215
ulint rows_added = 0;
22182216

22192217
if (dict_index_is_spatial(buf->index)) {
@@ -2237,13 +2235,24 @@ row_merge_read_clustered_index(
22372235
continue;
22382236
}
22392237

2238+
merge_file_t* file = &files[k++];
2239+
22402240
if (UNIV_LIKELY
22412241
(row && (rows_added = row_merge_buf_add(
22422242
buf, fts_index, old_table, new_table,
22432243
psort_info, row, ext, &doc_id,
22442244
conv_heap, &err,
22452245
&v_heap, eval_table, trx)))) {
22462246

2247+
/* Set the page flush observer for the
2248+
transaction when buffering the very first
2249+
record for a non-redo-logged operation. */
2250+
if (file->n_rec == 0 && i == 0
2251+
&& innodb_log_optimize_ddl) {
2252+
trx->set_flush_observer(
2253+
new_table->space, stage);
2254+
}
2255+
22472256
/* If we are creating FTS index,
22482257
a single row can generate more
22492258
records for tokenized word */
@@ -2383,7 +2392,7 @@ row_merge_read_clustered_index(
23832392
clust_btr_bulk = UT_NEW_NOKEY(
23842393
BtrBulk(index[i],
23852394
trx,
2386-
observer/**/));
2395+
trx->get_flush_observer()));
23872396
} else {
23882397
clust_btr_bulk->latch();
23892398
}
@@ -2495,8 +2504,9 @@ row_merge_read_clustered_index(
24952504
trx->error_key_num = i;
24962505
goto all_done;);
24972506

2498-
BtrBulk btr_bulk(index[i], trx,
2499-
observer);
2507+
BtrBulk btr_bulk(
2508+
index[i], trx,
2509+
trx->get_flush_observer());
25002510

25012511
err = row_merge_insert_index_tuples(
25022512
index[i], old_table,
@@ -4597,47 +4607,26 @@ row_merge_build_indexes(
45974607
}
45984608

45994609
trx_start_if_not_started_xa(trx, true);
4610+
ulint n_merge_files = 0;
46004611

4601-
/* Check if we need a flush observer to flush dirty pages.
4602-
Since we disable redo logging in bulk load, so we should flush
4603-
dirty pages before online log apply, because online log apply enables
4604-
redo logging(we can do further optimization here).
4605-
1. online add index: flush dirty pages right before row_log_apply().
4606-
2. table rebuild: flush dirty pages before row_log_table_apply().
4607-
4608-
we use bulk load to create all types of indexes except spatial index,
4609-
for which redo logging is enabled. If we create only spatial indexes,
4610-
we don't need to flush dirty pages at all. */
4611-
bool need_flush_observer = bool(innodb_log_optimize_ddl);
4612-
4613-
if (need_flush_observer) {
4614-
need_flush_observer = old_table != new_table;
4615-
4616-
for (i = 0; i < n_indexes; i++) {
4617-
if (!dict_index_is_spatial(indexes[i])) {
4618-
need_flush_observer = true;
4619-
}
4612+
for (ulint i = 0; i < n_indexes; i++)
4613+
{
4614+
if (!dict_index_is_spatial(indexes[i])) {
4615+
n_merge_files++;
46204616
}
46214617
}
46224618

4623-
FlushObserver* flush_observer = NULL;
4624-
if (need_flush_observer) {
4625-
flush_observer = UT_NEW_NOKEY(
4626-
FlushObserver(new_table->space, trx, stage));
4627-
4628-
trx_set_flush_observer(trx, flush_observer);
4629-
}
4630-
46314619
merge_files = static_cast<merge_file_t*>(
4632-
ut_malloc_nokey(n_indexes * sizeof *merge_files));
4620+
ut_malloc_nokey(n_merge_files * sizeof *merge_files));
46334621

46344622
/* Initialize all the merge file descriptors, so that we
46354623
don't call row_merge_file_destroy() on uninitialized
46364624
merge file descriptor */
46374625

4638-
for (i = 0; i < n_indexes; i++) {
4626+
for (i = 0; i < n_merge_files; i++) {
46394627
merge_files[i].fd = -1;
46404628
merge_files[i].offset = 0;
4629+
merge_files[i].n_rec = 0;
46414630
}
46424631

46434632
total_static_cost = COST_BUILD_INDEX_STATIC * n_indexes + COST_READ_CLUSTERED_INDEX;
@@ -4720,7 +4709,7 @@ row_merge_build_indexes(
47204709
" and create temporary files");
47214710
}
47224711

4723-
for (i = 0; i < n_indexes; i++) {
4712+
for (i = 0; i < n_merge_files; i++) {
47244713
total_index_blocks += merge_files[i].offset;
47254714
}
47264715

@@ -4733,7 +4722,7 @@ row_merge_build_indexes(
47334722
/* Now we have files containing index entries ready for
47344723
sorting and inserting. */
47354724

4736-
for (i = 0; i < n_indexes; i++) {
4725+
for (ulint k = 0, i = 0; i < n_indexes; i++) {
47374726
dict_index_t* sort_idx = indexes[i];
47384727

47394728
if (dict_index_is_spatial(sort_idx)) {
@@ -4812,13 +4801,13 @@ row_merge_build_indexes(
48124801
#ifdef FTS_INTERNAL_DIAG_PRINT
48134802
DEBUG_FTS_SORT_PRINT("FTS_SORT: Complete Insert\n");
48144803
#endif
4815-
} else if (merge_files[i].fd >= 0) {
4804+
} else if (merge_files[k].fd >= 0) {
48164805
char buf[NAME_LEN + 1];
48174806
row_merge_dup_t dup = {
48184807
sort_idx, table, col_map, 0};
48194808

48204809
pct_cost = (COST_BUILD_INDEX_STATIC +
4821-
(total_dynamic_cost * merge_files[i].offset /
4810+
(total_dynamic_cost * merge_files[k].offset /
48224811
total_index_blocks)) /
48234812
(total_static_cost + total_dynamic_cost)
48244813
* PCT_COST_MERGESORT_INDEX * 100;
@@ -4842,7 +4831,7 @@ row_merge_build_indexes(
48424831
}
48434832

48444833
error = row_merge_sort(
4845-
trx, &dup, &merge_files[i],
4834+
trx, &dup, &merge_files[k],
48464835
block, &tmpfd, true,
48474836
pct_progress, pct_cost,
48484837
crypt_block, new_table->space, stage);
@@ -4864,10 +4853,10 @@ row_merge_build_indexes(
48644853

48654854
if (error == DB_SUCCESS) {
48664855
BtrBulk btr_bulk(sort_idx, trx,
4867-
flush_observer);
4856+
trx->get_flush_observer());
48684857

48694858
pct_cost = (COST_BUILD_INDEX_STATIC +
4870-
(total_dynamic_cost * merge_files[i].offset /
4859+
(total_dynamic_cost * merge_files[k].offset /
48714860
total_index_blocks)) /
48724861
(total_static_cost + total_dynamic_cost) *
48734862
PCT_COST_INSERT_INDEX * 100;
@@ -4884,9 +4873,9 @@ row_merge_build_indexes(
48844873

48854874
error = row_merge_insert_index_tuples(
48864875
sort_idx, old_table,
4887-
merge_files[i].fd, block, NULL,
4876+
merge_files[k].fd, block, NULL,
48884877
&btr_bulk,
4889-
merge_files[i].n_rec, pct_progress, pct_cost,
4878+
merge_files[k].n_rec, pct_progress, pct_cost,
48904879
crypt_block, new_table->space, stage);
48914880

48924881
error = btr_bulk.finish(error);
@@ -4904,7 +4893,7 @@ row_merge_build_indexes(
49044893
}
49054894

49064895
/* Close the temporary file to free up space. */
4907-
row_merge_file_destroy(&merge_files[i]);
4896+
row_merge_file_destroy(&merge_files[k++]);
49084897

49094898
if (indexes[i]->type & DICT_FTS) {
49104899
row_fts_psort_info_destroy(psort_info, merge_info);
@@ -4916,7 +4905,12 @@ row_merge_build_indexes(
49164905
ut_ad(sort_idx->online_status
49174906
== ONLINE_INDEX_COMPLETE);
49184907
} else {
4919-
if (flush_observer) {
4908+
if (dict_index_is_spatial(indexes[i])) {
4909+
/* We never disable redo logging for
4910+
creating SPATIAL INDEX. Avoid writing any
4911+
unnecessary MLOG_INDEX_LOAD record. */
4912+
} else if (FlushObserver* flush_observer =
4913+
trx->get_flush_observer()) {
49204914
flush_observer->flush();
49214915
row_merge_write_redo(indexes[i]);
49224916
}
@@ -4958,7 +4952,7 @@ row_merge_build_indexes(
49584952

49594953
row_merge_file_destroy_low(tmpfd);
49604954

4961-
for (i = 0; i < n_indexes; i++) {
4955+
for (i = 0; i < n_merge_files; i++) {
49624956
row_merge_file_destroy(&merge_files[i]);
49634957
}
49644958

@@ -5015,8 +5009,7 @@ row_merge_build_indexes(
50155009

50165010
DBUG_EXECUTE_IF("ib_index_crash_after_bulk_load", DBUG_SUICIDE(););
50175011

5018-
if (flush_observer != NULL) {
5019-
ut_ad(need_flush_observer);
5012+
if (FlushObserver* flush_observer = trx->get_flush_observer()) {
50205013

50215014
DBUG_EXECUTE_IF("ib_index_build_fail_before_flush",
50225015
error = DB_INTERRUPTED;
@@ -5028,7 +5021,7 @@ row_merge_build_indexes(
50285021

50295022
flush_observer->flush();
50305023

5031-
UT_DELETE(flush_observer);
5024+
trx->remove_flush_observer();
50325025

50335026
if (trx_is_interrupted(trx)) {
50345027
error = DB_INTERRUPTED;

storage/innobase/trx/trx0trx.cc

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*****************************************************************************
22
33
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
4-
Copyright (c) 2015, 2018, MariaDB Corporation.
4+
Copyright (c) 2015, 2019, MariaDB Corporation.
55
66
This program is free software; you can redistribute it and/or modify it under
77
the terms of the GNU General Public License as published by the Free Software
@@ -64,17 +64,6 @@ typedef std::set<
6464
std::less<table_id_t>,
6565
ut_allocator<table_id_t> > table_id_set;
6666

67-
/** Set flush observer for the transaction
68-
@param[in/out] trx transaction struct
69-
@param[in] observer flush observer */
70-
void
71-
trx_set_flush_observer(
72-
trx_t* trx,
73-
FlushObserver* observer)
74-
{
75-
trx->flush_observer = observer;
76-
}
77-
7867
/*************************************************************//**
7968
Set detailed error message for the transaction. */
8069
void
@@ -165,7 +154,7 @@ trx_init(
165154

166155
trx->lock.table_cached = 0;
167156

168-
trx->flush_observer = NULL;
157+
ut_ad(trx->get_flush_observer() == NULL);
169158
}
170159

171160
/** For managing the life-cycle of the trx_t instance that we get
@@ -1088,6 +1077,21 @@ static trx_rseg_t* trx_assign_rseg_low()
10881077
return(rseg);
10891078
}
10901079

1080+
/** Set the innodb_log_optimize_ddl page flush observer
1081+
@param[in] space_id tablespace id
1082+
@param[in,out] stage performance_schema accounting */
1083+
void trx_t::set_flush_observer(ulint space_id, ut_stage_alter_t* stage)
1084+
{
1085+
flush_observer = UT_NEW_NOKEY(FlushObserver(space_id, this, stage));
1086+
}
1087+
1088+
/** Remove the flush observer */
1089+
void trx_t::remove_flush_observer()
1090+
{
1091+
UT_DELETE(flush_observer);
1092+
flush_observer = NULL;
1093+
}
1094+
10911095
/** Assign a rollback segment for modifying temporary tables.
10921096
@return the assigned rollback segment */
10931097
trx_rseg_t*

0 commit comments

Comments
 (0)