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.
This commit is contained in:
parent
38cad6875f
commit
0623cc7c16
@ -1,6 +1,7 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2014, 2015, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2019, 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
|
||||
@ -284,6 +285,7 @@ public:
|
||||
m_trx(trx),
|
||||
m_flush_observer(observer)
|
||||
{
|
||||
ut_ad(!dict_index_is_spatial(index));
|
||||
#ifdef UNIV_DEBUG
|
||||
if (m_flush_observer)
|
||||
fil_space_inc_redo_skipped_count(m_index->space);
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2015, 2018, MariaDB Corporation.
|
||||
Copyright (c) 2015, 2019, 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
|
||||
@ -40,20 +40,9 @@ Created 3/26/1996 Heikki Tuuri
|
||||
|
||||
// Forward declaration
|
||||
struct mtr_t;
|
||||
|
||||
// Forward declaration
|
||||
class ReadView;
|
||||
|
||||
// Forward declaration
|
||||
class FlushObserver;
|
||||
|
||||
/** Set flush observer for the transaction
|
||||
@param[in/out] trx transaction struct
|
||||
@param[in] observer flush observer */
|
||||
void
|
||||
trx_set_flush_observer(
|
||||
trx_t* trx,
|
||||
FlushObserver* observer);
|
||||
class ut_stage_alter_t;
|
||||
|
||||
/******************************************************************//**
|
||||
Set detailed error message for the transaction. */
|
||||
@ -1132,8 +1121,11 @@ struct trx_t {
|
||||
/*------------------------------*/
|
||||
char* detailed_error; /*!< detailed error message for last
|
||||
error, or empty. */
|
||||
FlushObserver* flush_observer; /*!< flush observer */
|
||||
|
||||
private:
|
||||
/** flush observer used to track flushing of non-redo logged pages
|
||||
during bulk create index */
|
||||
FlushObserver* flush_observer;
|
||||
public:
|
||||
/* Lock wait statistics */
|
||||
ulint n_rec_lock_waits;
|
||||
/*!< Number of record lock waits,
|
||||
@ -1177,6 +1169,20 @@ struct trx_t {
|
||||
return(assign_temp_rseg());
|
||||
}
|
||||
|
||||
/** Set the innodb_log_optimize_ddl page flush observer
|
||||
@param[in] space_id tablespace id
|
||||
@param[in,out] stage performance_schema accounting */
|
||||
void set_flush_observer(ulint space_id, ut_stage_alter_t* stage);
|
||||
|
||||
/** Remove the flush observer */
|
||||
void remove_flush_observer();
|
||||
|
||||
/** @return the flush observer */
|
||||
FlushObserver* get_flush_observer() const
|
||||
{
|
||||
return flush_observer;
|
||||
}
|
||||
|
||||
private:
|
||||
/** Assign a rollback segment for modifying temporary tables.
|
||||
@return the assigned rollback segment */
|
||||
|
@ -1673,7 +1673,7 @@ row_fts_merge_insert(
|
||||
/* Create bulk load instance */
|
||||
ins_ctx.btr_bulk = UT_NEW_NOKEY(
|
||||
BtrBulk(aux_index, trx, psort_info[0].psort_common->trx
|
||||
->flush_observer));
|
||||
->get_flush_observer()));
|
||||
|
||||
/* Create tuple for insert */
|
||||
ins_ctx.tuple = dtuple_create(heap, dict_index_get_n_fields(aux_index));
|
||||
|
@ -1736,7 +1736,6 @@ row_merge_read_clustered_index(
|
||||
mem_heap_t* mtuple_heap = NULL;
|
||||
mtuple_t prev_mtuple;
|
||||
mem_heap_t* conv_heap = NULL;
|
||||
FlushObserver* observer = trx->flush_observer;
|
||||
double curr_progress = 0.0;
|
||||
ib_uint64_t read_rows = 0;
|
||||
ib_uint64_t table_total_rows = 0;
|
||||
@ -2211,9 +2210,8 @@ write_buffers:
|
||||
bool skip_sort = skip_pk_sort
|
||||
&& dict_index_is_clust(merge_buf[0]->index);
|
||||
|
||||
for (ulint i = 0; i < n_index; i++, skip_sort = false) {
|
||||
for (ulint k = 0, i = 0; i < n_index; i++, skip_sort = false) {
|
||||
row_merge_buf_t* buf = merge_buf[i];
|
||||
merge_file_t* file = &files[i];
|
||||
ulint rows_added = 0;
|
||||
|
||||
if (dict_index_is_spatial(buf->index)) {
|
||||
@ -2237,6 +2235,8 @@ write_buffers:
|
||||
continue;
|
||||
}
|
||||
|
||||
merge_file_t* file = &files[k++];
|
||||
|
||||
if (UNIV_LIKELY
|
||||
(row && (rows_added = row_merge_buf_add(
|
||||
buf, fts_index, old_table, new_table,
|
||||
@ -2244,6 +2244,15 @@ write_buffers:
|
||||
conv_heap, &err,
|
||||
&v_heap, eval_table, trx)))) {
|
||||
|
||||
/* Set the page flush observer for the
|
||||
transaction when buffering the very first
|
||||
record for a non-redo-logged operation. */
|
||||
if (file->n_rec == 0 && i == 0
|
||||
&& innodb_log_optimize_ddl) {
|
||||
trx->set_flush_observer(
|
||||
new_table->space, stage);
|
||||
}
|
||||
|
||||
/* If we are creating FTS index,
|
||||
a single row can generate more
|
||||
records for tokenized word */
|
||||
@ -2383,7 +2392,7 @@ write_buffers:
|
||||
clust_btr_bulk = UT_NEW_NOKEY(
|
||||
BtrBulk(index[i],
|
||||
trx,
|
||||
observer/**/));
|
||||
trx->get_flush_observer()));
|
||||
} else {
|
||||
clust_btr_bulk->latch();
|
||||
}
|
||||
@ -2495,8 +2504,9 @@ write_buffers:
|
||||
trx->error_key_num = i;
|
||||
goto all_done;);
|
||||
|
||||
BtrBulk btr_bulk(index[i], trx,
|
||||
observer);
|
||||
BtrBulk btr_bulk(
|
||||
index[i], trx,
|
||||
trx->get_flush_observer());
|
||||
|
||||
err = row_merge_insert_index_tuples(
|
||||
index[i], old_table,
|
||||
@ -4597,47 +4607,26 @@ row_merge_build_indexes(
|
||||
}
|
||||
|
||||
trx_start_if_not_started_xa(trx, true);
|
||||
ulint n_merge_files = 0;
|
||||
|
||||
/* Check if we need a flush observer to flush dirty pages.
|
||||
Since we disable redo logging in bulk load, so we should flush
|
||||
dirty pages before online log apply, because online log apply enables
|
||||
redo logging(we can do further optimization here).
|
||||
1. online add index: flush dirty pages right before row_log_apply().
|
||||
2. table rebuild: flush dirty pages before row_log_table_apply().
|
||||
|
||||
we use bulk load to create all types of indexes except spatial index,
|
||||
for which redo logging is enabled. If we create only spatial indexes,
|
||||
we don't need to flush dirty pages at all. */
|
||||
bool need_flush_observer = bool(innodb_log_optimize_ddl);
|
||||
|
||||
if (need_flush_observer) {
|
||||
need_flush_observer = old_table != new_table;
|
||||
|
||||
for (i = 0; i < n_indexes; i++) {
|
||||
if (!dict_index_is_spatial(indexes[i])) {
|
||||
need_flush_observer = true;
|
||||
}
|
||||
for (ulint i = 0; i < n_indexes; i++)
|
||||
{
|
||||
if (!dict_index_is_spatial(indexes[i])) {
|
||||
n_merge_files++;
|
||||
}
|
||||
}
|
||||
|
||||
FlushObserver* flush_observer = NULL;
|
||||
if (need_flush_observer) {
|
||||
flush_observer = UT_NEW_NOKEY(
|
||||
FlushObserver(new_table->space, trx, stage));
|
||||
|
||||
trx_set_flush_observer(trx, flush_observer);
|
||||
}
|
||||
|
||||
merge_files = static_cast<merge_file_t*>(
|
||||
ut_malloc_nokey(n_indexes * sizeof *merge_files));
|
||||
ut_malloc_nokey(n_merge_files * sizeof *merge_files));
|
||||
|
||||
/* Initialize all the merge file descriptors, so that we
|
||||
don't call row_merge_file_destroy() on uninitialized
|
||||
merge file descriptor */
|
||||
|
||||
for (i = 0; i < n_indexes; i++) {
|
||||
for (i = 0; i < n_merge_files; i++) {
|
||||
merge_files[i].fd = -1;
|
||||
merge_files[i].offset = 0;
|
||||
merge_files[i].n_rec = 0;
|
||||
}
|
||||
|
||||
total_static_cost = COST_BUILD_INDEX_STATIC * n_indexes + COST_READ_CLUSTERED_INDEX;
|
||||
@ -4720,7 +4709,7 @@ row_merge_build_indexes(
|
||||
" and create temporary files");
|
||||
}
|
||||
|
||||
for (i = 0; i < n_indexes; i++) {
|
||||
for (i = 0; i < n_merge_files; i++) {
|
||||
total_index_blocks += merge_files[i].offset;
|
||||
}
|
||||
|
||||
@ -4733,7 +4722,7 @@ row_merge_build_indexes(
|
||||
/* Now we have files containing index entries ready for
|
||||
sorting and inserting. */
|
||||
|
||||
for (i = 0; i < n_indexes; i++) {
|
||||
for (ulint k = 0, i = 0; i < n_indexes; i++) {
|
||||
dict_index_t* sort_idx = indexes[i];
|
||||
|
||||
if (dict_index_is_spatial(sort_idx)) {
|
||||
@ -4812,13 +4801,13 @@ wait_again:
|
||||
#ifdef FTS_INTERNAL_DIAG_PRINT
|
||||
DEBUG_FTS_SORT_PRINT("FTS_SORT: Complete Insert\n");
|
||||
#endif
|
||||
} else if (merge_files[i].fd >= 0) {
|
||||
} else if (merge_files[k].fd >= 0) {
|
||||
char buf[NAME_LEN + 1];
|
||||
row_merge_dup_t dup = {
|
||||
sort_idx, table, col_map, 0};
|
||||
|
||||
pct_cost = (COST_BUILD_INDEX_STATIC +
|
||||
(total_dynamic_cost * merge_files[i].offset /
|
||||
(total_dynamic_cost * merge_files[k].offset /
|
||||
total_index_blocks)) /
|
||||
(total_static_cost + total_dynamic_cost)
|
||||
* PCT_COST_MERGESORT_INDEX * 100;
|
||||
@ -4842,7 +4831,7 @@ wait_again:
|
||||
}
|
||||
|
||||
error = row_merge_sort(
|
||||
trx, &dup, &merge_files[i],
|
||||
trx, &dup, &merge_files[k],
|
||||
block, &tmpfd, true,
|
||||
pct_progress, pct_cost,
|
||||
crypt_block, new_table->space, stage);
|
||||
@ -4864,10 +4853,10 @@ wait_again:
|
||||
|
||||
if (error == DB_SUCCESS) {
|
||||
BtrBulk btr_bulk(sort_idx, trx,
|
||||
flush_observer);
|
||||
trx->get_flush_observer());
|
||||
|
||||
pct_cost = (COST_BUILD_INDEX_STATIC +
|
||||
(total_dynamic_cost * merge_files[i].offset /
|
||||
(total_dynamic_cost * merge_files[k].offset /
|
||||
total_index_blocks)) /
|
||||
(total_static_cost + total_dynamic_cost) *
|
||||
PCT_COST_INSERT_INDEX * 100;
|
||||
@ -4884,9 +4873,9 @@ wait_again:
|
||||
|
||||
error = row_merge_insert_index_tuples(
|
||||
sort_idx, old_table,
|
||||
merge_files[i].fd, block, NULL,
|
||||
merge_files[k].fd, block, NULL,
|
||||
&btr_bulk,
|
||||
merge_files[i].n_rec, pct_progress, pct_cost,
|
||||
merge_files[k].n_rec, pct_progress, pct_cost,
|
||||
crypt_block, new_table->space, stage);
|
||||
|
||||
error = btr_bulk.finish(error);
|
||||
@ -4904,7 +4893,7 @@ wait_again:
|
||||
}
|
||||
|
||||
/* Close the temporary file to free up space. */
|
||||
row_merge_file_destroy(&merge_files[i]);
|
||||
row_merge_file_destroy(&merge_files[k++]);
|
||||
|
||||
if (indexes[i]->type & DICT_FTS) {
|
||||
row_fts_psort_info_destroy(psort_info, merge_info);
|
||||
@ -4916,7 +4905,12 @@ wait_again:
|
||||
ut_ad(sort_idx->online_status
|
||||
== ONLINE_INDEX_COMPLETE);
|
||||
} else {
|
||||
if (flush_observer) {
|
||||
if (dict_index_is_spatial(indexes[i])) {
|
||||
/* We never disable redo logging for
|
||||
creating SPATIAL INDEX. Avoid writing any
|
||||
unnecessary MLOG_INDEX_LOAD record. */
|
||||
} else if (FlushObserver* flush_observer =
|
||||
trx->get_flush_observer()) {
|
||||
flush_observer->flush();
|
||||
row_merge_write_redo(indexes[i]);
|
||||
}
|
||||
@ -4958,7 +4952,7 @@ func_exit:
|
||||
|
||||
row_merge_file_destroy_low(tmpfd);
|
||||
|
||||
for (i = 0; i < n_indexes; i++) {
|
||||
for (i = 0; i < n_merge_files; i++) {
|
||||
row_merge_file_destroy(&merge_files[i]);
|
||||
}
|
||||
|
||||
@ -5015,8 +5009,7 @@ func_exit:
|
||||
|
||||
DBUG_EXECUTE_IF("ib_index_crash_after_bulk_load", DBUG_SUICIDE(););
|
||||
|
||||
if (flush_observer != NULL) {
|
||||
ut_ad(need_flush_observer);
|
||||
if (FlushObserver* flush_observer = trx->get_flush_observer()) {
|
||||
|
||||
DBUG_EXECUTE_IF("ib_index_build_fail_before_flush",
|
||||
error = DB_INTERRUPTED;
|
||||
@ -5028,7 +5021,7 @@ func_exit:
|
||||
|
||||
flush_observer->flush();
|
||||
|
||||
UT_DELETE(flush_observer);
|
||||
trx->remove_flush_observer();
|
||||
|
||||
if (trx_is_interrupted(trx)) {
|
||||
error = DB_INTERRUPTED;
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2015, 2018, MariaDB Corporation.
|
||||
Copyright (c) 2015, 2019, 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
|
||||
@ -64,17 +64,6 @@ typedef std::set<
|
||||
std::less<table_id_t>,
|
||||
ut_allocator<table_id_t> > table_id_set;
|
||||
|
||||
/** Set flush observer for the transaction
|
||||
@param[in/out] trx transaction struct
|
||||
@param[in] observer flush observer */
|
||||
void
|
||||
trx_set_flush_observer(
|
||||
trx_t* trx,
|
||||
FlushObserver* observer)
|
||||
{
|
||||
trx->flush_observer = observer;
|
||||
}
|
||||
|
||||
/*************************************************************//**
|
||||
Set detailed error message for the transaction. */
|
||||
void
|
||||
@ -165,7 +154,7 @@ trx_init(
|
||||
|
||||
trx->lock.table_cached = 0;
|
||||
|
||||
trx->flush_observer = NULL;
|
||||
ut_ad(trx->get_flush_observer() == NULL);
|
||||
}
|
||||
|
||||
/** 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()
|
||||
return(rseg);
|
||||
}
|
||||
|
||||
/** Set the innodb_log_optimize_ddl page flush observer
|
||||
@param[in] space_id tablespace id
|
||||
@param[in,out] stage performance_schema accounting */
|
||||
void trx_t::set_flush_observer(ulint space_id, ut_stage_alter_t* stage)
|
||||
{
|
||||
flush_observer = UT_NEW_NOKEY(FlushObserver(space_id, this, stage));
|
||||
}
|
||||
|
||||
/** Remove the flush observer */
|
||||
void trx_t::remove_flush_observer()
|
||||
{
|
||||
UT_DELETE(flush_observer);
|
||||
flush_observer = NULL;
|
||||
}
|
||||
|
||||
/** Assign a rollback segment for modifying temporary tables.
|
||||
@return the assigned rollback segment */
|
||||
trx_rseg_t*
|
||||
|
Loading…
x
Reference in New Issue
Block a user