diff options
author | Jan Lindström <jan.lindstrom@mariadb.com> | 2015-10-27 13:00:15 +0200 |
---|---|---|
committer | Jan Lindström <jan.lindstrom@mariadb.com> | 2015-10-27 13:00:15 +0200 |
commit | 13884cf206c7e1a828748173a4d723cfe186fd8a (patch) | |
tree | f5908ebcee44143dbce1443d9656bfdbe943db61 | |
parent | d6480f49ffb8a2a6e63915a55aa8bd067b0850e5 (diff) | |
download | mariadb-git-13884cf206c7e1a828748173a4d723cfe186fd8a.tar.gz |
MDEV-8696: Adding indexes on empty table is slow with large innodb_sort_buffer_size.
Analysis: Current implementation will write and read at least one block
(sort_buffer_size bytes) from disk / index even if that block does not
contain any records.
Fix: Avoid writing / reading empty blocks to temporary files (disk).
19 files changed, 297 insertions, 42 deletions
diff --git a/mysql-test/suite/innodb/r/innodb-alter-filewrite.result b/mysql-test/suite/innodb/r/innodb-alter-filewrite.result new file mode 100644 index 00000000000..444b09ad440 --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb-alter-filewrite.result @@ -0,0 +1,30 @@ +CREATE TABLE `test_wo_keys` ( +`f01` int AUTO_INCREMENT, +`f02` bigint, `f03` bigint, `f04` enum('a','b'), +`f05` date, `f06` int, `f07` int, `f08` double, `f09` int, +`f10` bigint, `f11` double, `f12` enum('a','b','c','d','e'), +`f13` int, `f14` int, `f15` varchar(255), `f16` int, `f17` int, `f18` int, +`f19` double, `f20` double, `f21` double, `f22` double, `f23` double, `f24` tinyint, +`f25` double, `f26` double, `f27` double, `f28` double, `f29` int unsigned, +`f30` int unsigned, `f31` bigint, `f32` int unsigned, `f33` bigint, +`f34` int unsigned, `f35` int unsigned, +PRIMARY KEY `f01` (`f01`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +show status like '%merge_buffers%'; +Variable_name Value +Innodb_os_merge_buffers_written 0 +Innodb_os_merge_buffers_read 0 +Innodb_os_merge_buffers_merged 0 +ALTER TABLE test_wo_keys +ADD KEY `f06` (`f06`), ADD KEY `f05` (`f05`), ADD KEY `f04` (`f04`), ADD KEY `f23` (`f23`), +ADD KEY `f10` (`f10`), ADD KEY `f11` (`f11`), ADD KEY `f09` (`f09`), ADD KEY `f22` (`f22`), +ADD KEY `f21` (`f21`), ADD KEY `f07` (`f07`), ADD KEY `f08` (`f08`), ADD KEY `f18` (`f18`), +ADD KEY `f19` (`f19`), ADD KEY `f20` (`f20`), ADD KEY `f29` (`f29`,`f31`,`f33`), +ADD KEY `f35` (`f35`), ADD KEY `f25` (`f25`), ADD KEY `f26` (`f26`), +ADD KEY `f27` (`f27`), ADD KEY `f28` (`f28`); +show status like '%merge_buffers%'; +Variable_name Value +Innodb_os_merge_buffers_written 0 +Innodb_os_merge_buffers_read 0 +Innodb_os_merge_buffers_merged 0 +DROP TABLE test_wo_keys; diff --git a/mysql-test/suite/innodb/r/innodb_monitor.result b/mysql-test/suite/innodb/r/innodb_monitor.result index f8d24f4e6f5..89ce676e38b 100644 --- a/mysql-test/suite/innodb/r/innodb_monitor.result +++ b/mysql-test/suite/innodb/r/innodb_monitor.result @@ -123,6 +123,9 @@ os_log_bytes_written disabled os_log_fsyncs disabled os_log_pending_fsyncs disabled os_log_pending_writes disabled +os_merge_blocks_written disabled +os_merge_blocks_read disabled +os_merge_blocks_merged disabled trx_rw_commits disabled trx_ro_commits disabled trx_nl_ro_commits disabled @@ -254,6 +257,9 @@ lock_row_lock_time disabled lock_row_lock_time_max disabled lock_row_lock_waits disabled lock_row_lock_time_avg disabled +os_merge_blocks_written disabled +os_merge_blocks_read disabled +os_merge_blocks_merged disabled innodb_rwlock_s_spin_waits disabled innodb_rwlock_x_spin_waits disabled innodb_rwlock_s_spin_rounds disabled @@ -292,6 +298,9 @@ os_log_bytes_written disabled os_log_fsyncs disabled os_log_pending_fsyncs enabled os_log_pending_writes enabled +os_merge_blocks_written disabled +os_merge_blocks_read disabled +os_merge_blocks_merged disabled set global innodb_monitor_enable=""; ERROR 42000: Variable 'innodb_monitor_enable' can't be set to the value of '' set global innodb_monitor_enable="_"; diff --git a/mysql-test/suite/innodb/t/innodb-alter-filewrite.test b/mysql-test/suite/innodb/t/innodb-alter-filewrite.test new file mode 100644 index 00000000000..d0372056937 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb-alter-filewrite.test @@ -0,0 +1,32 @@ +--source include/have_innodb.inc + +# +# MDEV-8696: Adding indexes on empty table is slow with large innodb_sort_buffer_size. +# + +CREATE TABLE `test_wo_keys` ( +`f01` int AUTO_INCREMENT, +`f02` bigint, `f03` bigint, `f04` enum('a','b'), +`f05` date, `f06` int, `f07` int, `f08` double, `f09` int, +`f10` bigint, `f11` double, `f12` enum('a','b','c','d','e'), +`f13` int, `f14` int, `f15` varchar(255), `f16` int, `f17` int, `f18` int, +`f19` double, `f20` double, `f21` double, `f22` double, `f23` double, `f24` tinyint, +`f25` double, `f26` double, `f27` double, `f28` double, `f29` int unsigned, +`f30` int unsigned, `f31` bigint, `f32` int unsigned, `f33` bigint, +`f34` int unsigned, `f35` int unsigned, +PRIMARY KEY `f01` (`f01`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; + +show status like '%merge_buffers%'; + +ALTER TABLE test_wo_keys +ADD KEY `f06` (`f06`), ADD KEY `f05` (`f05`), ADD KEY `f04` (`f04`), ADD KEY `f23` (`f23`), +ADD KEY `f10` (`f10`), ADD KEY `f11` (`f11`), ADD KEY `f09` (`f09`), ADD KEY `f22` (`f22`), +ADD KEY `f21` (`f21`), ADD KEY `f07` (`f07`), ADD KEY `f08` (`f08`), ADD KEY `f18` (`f18`), +ADD KEY `f19` (`f19`), ADD KEY `f20` (`f20`), ADD KEY `f29` (`f29`,`f31`,`f33`), +ADD KEY `f35` (`f35`), ADD KEY `f25` (`f25`), ADD KEY `f26` (`f26`), +ADD KEY `f27` (`f27`), ADD KEY `f28` (`f28`); + +show status like '%merge_buffers%'; + +DROP TABLE test_wo_keys; diff --git a/mysql-test/suite/sys_vars/r/innodb_monitor_disable_basic.result b/mysql-test/suite/sys_vars/r/innodb_monitor_disable_basic.result index 8c0af874228..654b6fc51dd 100644 --- a/mysql-test/suite/sys_vars/r/innodb_monitor_disable_basic.result +++ b/mysql-test/suite/sys_vars/r/innodb_monitor_disable_basic.result @@ -123,6 +123,9 @@ os_log_bytes_written disabled os_log_fsyncs disabled os_log_pending_fsyncs disabled os_log_pending_writes disabled +os_merge_blocks_written disabled +os_merge_blocks_read disabled +os_merge_blocks_merged disabled trx_rw_commits disabled trx_ro_commits disabled trx_nl_ro_commits disabled @@ -254,6 +257,9 @@ lock_row_lock_time disabled lock_row_lock_time_max disabled lock_row_lock_waits disabled lock_row_lock_time_avg disabled +os_merge_blocks_written disabled +os_merge_blocks_read disabled +os_merge_blocks_merged disabled innodb_rwlock_s_spin_waits disabled innodb_rwlock_x_spin_waits disabled innodb_rwlock_s_spin_rounds disabled @@ -292,6 +298,9 @@ os_log_bytes_written disabled os_log_fsyncs disabled os_log_pending_fsyncs enabled os_log_pending_writes enabled +os_merge_blocks_written disabled +os_merge_blocks_read disabled +os_merge_blocks_merged disabled set global innodb_monitor_enable=""; ERROR 42000: Variable 'innodb_monitor_enable' can't be set to the value of '' set global innodb_monitor_enable="_"; diff --git a/mysql-test/suite/sys_vars/r/innodb_monitor_enable_basic.result b/mysql-test/suite/sys_vars/r/innodb_monitor_enable_basic.result index 8c0af874228..654b6fc51dd 100644 --- a/mysql-test/suite/sys_vars/r/innodb_monitor_enable_basic.result +++ b/mysql-test/suite/sys_vars/r/innodb_monitor_enable_basic.result @@ -123,6 +123,9 @@ os_log_bytes_written disabled os_log_fsyncs disabled os_log_pending_fsyncs disabled os_log_pending_writes disabled +os_merge_blocks_written disabled +os_merge_blocks_read disabled +os_merge_blocks_merged disabled trx_rw_commits disabled trx_ro_commits disabled trx_nl_ro_commits disabled @@ -254,6 +257,9 @@ lock_row_lock_time disabled lock_row_lock_time_max disabled lock_row_lock_waits disabled lock_row_lock_time_avg disabled +os_merge_blocks_written disabled +os_merge_blocks_read disabled +os_merge_blocks_merged disabled innodb_rwlock_s_spin_waits disabled innodb_rwlock_x_spin_waits disabled innodb_rwlock_s_spin_rounds disabled @@ -292,6 +298,9 @@ os_log_bytes_written disabled os_log_fsyncs disabled os_log_pending_fsyncs enabled os_log_pending_writes enabled +os_merge_blocks_written disabled +os_merge_blocks_read disabled +os_merge_blocks_merged disabled set global innodb_monitor_enable=""; ERROR 42000: Variable 'innodb_monitor_enable' can't be set to the value of '' set global innodb_monitor_enable="_"; diff --git a/mysql-test/suite/sys_vars/r/innodb_monitor_reset_all_basic.result b/mysql-test/suite/sys_vars/r/innodb_monitor_reset_all_basic.result index 8c0af874228..654b6fc51dd 100644 --- a/mysql-test/suite/sys_vars/r/innodb_monitor_reset_all_basic.result +++ b/mysql-test/suite/sys_vars/r/innodb_monitor_reset_all_basic.result @@ -123,6 +123,9 @@ os_log_bytes_written disabled os_log_fsyncs disabled os_log_pending_fsyncs disabled os_log_pending_writes disabled +os_merge_blocks_written disabled +os_merge_blocks_read disabled +os_merge_blocks_merged disabled trx_rw_commits disabled trx_ro_commits disabled trx_nl_ro_commits disabled @@ -254,6 +257,9 @@ lock_row_lock_time disabled lock_row_lock_time_max disabled lock_row_lock_waits disabled lock_row_lock_time_avg disabled +os_merge_blocks_written disabled +os_merge_blocks_read disabled +os_merge_blocks_merged disabled innodb_rwlock_s_spin_waits disabled innodb_rwlock_x_spin_waits disabled innodb_rwlock_s_spin_rounds disabled @@ -292,6 +298,9 @@ os_log_bytes_written disabled os_log_fsyncs disabled os_log_pending_fsyncs enabled os_log_pending_writes enabled +os_merge_blocks_written disabled +os_merge_blocks_read disabled +os_merge_blocks_merged disabled set global innodb_monitor_enable=""; ERROR 42000: Variable 'innodb_monitor_enable' can't be set to the value of '' set global innodb_monitor_enable="_"; diff --git a/mysql-test/suite/sys_vars/r/innodb_monitor_reset_basic.result b/mysql-test/suite/sys_vars/r/innodb_monitor_reset_basic.result index 8c0af874228..654b6fc51dd 100644 --- a/mysql-test/suite/sys_vars/r/innodb_monitor_reset_basic.result +++ b/mysql-test/suite/sys_vars/r/innodb_monitor_reset_basic.result @@ -123,6 +123,9 @@ os_log_bytes_written disabled os_log_fsyncs disabled os_log_pending_fsyncs disabled os_log_pending_writes disabled +os_merge_blocks_written disabled +os_merge_blocks_read disabled +os_merge_blocks_merged disabled trx_rw_commits disabled trx_ro_commits disabled trx_nl_ro_commits disabled @@ -254,6 +257,9 @@ lock_row_lock_time disabled lock_row_lock_time_max disabled lock_row_lock_waits disabled lock_row_lock_time_avg disabled +os_merge_blocks_written disabled +os_merge_blocks_read disabled +os_merge_blocks_merged disabled innodb_rwlock_s_spin_waits disabled innodb_rwlock_x_spin_waits disabled innodb_rwlock_s_spin_rounds disabled @@ -292,6 +298,9 @@ os_log_bytes_written disabled os_log_fsyncs disabled os_log_pending_fsyncs enabled os_log_pending_writes enabled +os_merge_blocks_written disabled +os_merge_blocks_read disabled +os_merge_blocks_merged disabled set global innodb_monitor_enable=""; ERROR 42000: Variable 'innodb_monitor_enable' can't be set to the value of '' set global innodb_monitor_enable="_"; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 3e7b471a609..926fb0580bb 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -4,7 +4,7 @@ Copyright (c) 2000, 2015, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, 2009 Google Inc. Copyright (c) 2009, Percona Inc. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2013, 2014 SkySQL Ab. All Rights Reserved. +Copyright (c) 2013, 2015, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -644,6 +644,12 @@ static SHOW_VAR innodb_status_variables[]= { (char*) &export_vars.innodb_os_log_pending_writes, SHOW_LONG}, {"os_log_written", (char*) &export_vars.innodb_os_log_written, SHOW_LONGLONG}, + {"os_merge_buffers_written", + (char*) &export_vars.innodb_merge_buffers_written, SHOW_LONGLONG}, + {"os_merge_buffers_read", + (char*) &export_vars.innodb_merge_buffers_read, SHOW_LONGLONG}, + {"os_merge_buffers_merged", + (char*) &export_vars.innodb_merge_buffers_merged, SHOW_LONGLONG}, {"page_size", (char*) &export_vars.innodb_page_size, SHOW_LONG}, {"pages_created", diff --git a/storage/innobase/include/srv0mon.h b/storage/innobase/include/srv0mon.h index 2d90f47eefe..d2b65721e1a 100644 --- a/storage/innobase/include/srv0mon.h +++ b/storage/innobase/include/srv0mon.h @@ -2,6 +2,7 @@ Copyright (c) 2010, 2013, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. +Copyright (c) 2014, 2015, 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 @@ -255,6 +256,9 @@ enum monitor_id_t { MONITOR_OVLD_OS_LOG_FSYNC, MONITOR_OVLD_OS_LOG_PENDING_FSYNC, MONITOR_OVLD_OS_LOG_PENDING_WRITES, + MONITOR_MERGE_BLOCKS_WRITTEN, + MONITOR_MERGE_BLOCKS_READ, + MONITOR_MERGE_BLOCKS_MERGED, /* Transaction related counters */ MONITOR_MODULE_TRX, diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index 63b73a07746..338ad552ab4 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -3,7 +3,7 @@ Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved. Copyright (c) 2008, 2009, Google Inc. Copyright (c) 2009, Percona Inc. -Copyright (c) 2013, 2014, SkySQL Ab. All Rights Reserved. +Copyright (c) 2013, 2015, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -138,6 +138,15 @@ struct srv_stats_t { /** Number of system rows inserted */ ulint_ctr_64_t n_system_rows_inserted; + + /** Number of merge buffers written */ + ulint_ctr_64_t merge_buffers_written; + + /** Number of merge buffers read */ + ulint_ctr_64_t merge_buffers_read; + + /** Number of merge buffers merged */ + ulint_ctr_64_t merge_buffers_merged; }; extern const char* srv_main_thread_op_info; @@ -875,6 +884,9 @@ struct export_var_t{ ulint innodb_purge_view_trx_id_age; /*!< rw_max_trx_id - purged view's min trx_id */ #endif /* UNIV_DEBUG */ + ib_int64_t innodb_merge_buffers_written; + ib_int64_t innodb_merge_buffers_read; + ib_int64_t innodb_merge_buffers_merged; }; /** Thread slot in the thread table. */ diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc index 284081d4b0c..75aa423b2ac 100644 --- a/storage/innobase/row/row0merge.cc +++ b/storage/innobase/row/row0merge.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2005, 2015, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2014, 2015, 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 @@ -871,6 +872,8 @@ row_merge_read( success = os_file_read_no_error_handling(OS_FILE_FROM_FD(fd), buf, ofs, srv_sort_buf_size); + srv_stats.merge_buffers_read.inc(); + #ifdef POSIX_FADV_DONTNEED /* Each block is read exactly once. Free up the file cache. */ posix_fadvise(fd, ofs, srv_sort_buf_size, POSIX_FADV_DONTNEED); @@ -905,6 +908,7 @@ row_merge_write( DBUG_EXECUTE_IF("row_merge_write_failure", return(FALSE);); ret = os_file_write("(merge)", OS_FILE_FROM_FD(fd), buf, ofs, buf_len); + srv_stats.merge_buffers_written.inc(); #ifdef UNIV_DEBUG if (row_merge_print_block_write) { @@ -1736,7 +1740,7 @@ write_buffers: /* We have enough data tuples to form a block. Sort them and write to disk. */ - if (buf->n_tuples) { + if (UNIV_LIKELY(buf->n_tuples)) { if (dict_index_is_unique(buf->index)) { row_merge_dup_t dup = { buf->index, table, col_map, 0}; @@ -1777,13 +1781,17 @@ write_buffers: dict_index_get_lock(buf->index)); } - row_merge_buf_write(buf, file, block); + /* Do not write empty buffers to temporary file */ + if (buf->n_tuples) { + + row_merge_buf_write(buf, file, block); - if (!row_merge_write(file->fd, file->offset++, - block)) { - err = DB_TEMP_FILE_WRITE_FAILURE; - trx->error_key_num = i; - break; + if (!row_merge_write(file->fd, file->offset++, + block)) { + err = DB_TEMP_FILE_WRITE_FAILURE; + trx->error_key_num = i; + break; + } } UNIV_MEM_INVALID(&block[0], srv_sort_buf_size); @@ -2068,6 +2076,9 @@ done1: mem_heap_free(heap); b2 = row_merge_write_eof(&block[2 * srv_sort_buf_size], b2, of->fd, &of->offset); + + srv_stats.merge_buffers_merged.inc(); + return(b2 ? DB_SUCCESS : DB_CORRUPTION); } @@ -3747,17 +3758,21 @@ wait_again: DEBUG_FTS_SORT_PRINT("FTS_SORT: Complete Insert\n"); #endif } else { - row_merge_dup_t dup = { - sort_idx, table, col_map, 0}; - - error = row_merge_sort( - trx, &dup, &merge_files[i], - block, &tmpfd); - - if (error == DB_SUCCESS) { - error = row_merge_insert_index_tuples( - trx->id, sort_idx, old_table, - merge_files[i].fd, block); + /* Sorting and inserting is required only if + there really is records */ + if (UNIV_LIKELY(merge_files[i].n_rec)) { + row_merge_dup_t dup = { + sort_idx, table, col_map, 0}; + + error = row_merge_sort( + trx, &dup, &merge_files[i], + block, &tmpfd); + + if (error == DB_SUCCESS) { + error = row_merge_insert_index_tuples( + trx->id, sort_idx, old_table, + merge_files[i].fd, block); + } } } diff --git a/storage/innobase/srv/srv0mon.cc b/storage/innobase/srv/srv0mon.cc index a0dd32c203f..960c889f871 100644 --- a/storage/innobase/srv/srv0mon.cc +++ b/storage/innobase/srv/srv0mon.cc @@ -2,6 +2,7 @@ Copyright (c) 2010, 2014, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. +Copyright (c) 2014, 2015, 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 @@ -674,6 +675,24 @@ static monitor_info_t innodb_counter_info[] = MONITOR_EXISTING | MONITOR_DEFAULT_ON), MONITOR_DEFAULT_START, MONITOR_OVLD_OS_LOG_PENDING_WRITES}, + {"os_merge_blocks_written", "os", + "Number of merge blocks written (innodb_os_merge_blocks_written)", + static_cast<monitor_type_t>( + MONITOR_EXISTING | MONITOR_DEFAULT_ON), + MONITOR_DEFAULT_START, MONITOR_MERGE_BLOCKS_WRITTEN}, + + {"os_merge_blocks_read", "os", + "Number of merge blocks read (innodb_os_merge_blocks_read)", + static_cast<monitor_type_t>( + MONITOR_EXISTING | MONITOR_DEFAULT_ON), + MONITOR_DEFAULT_START, MONITOR_MERGE_BLOCKS_READ}, + + {"os_merge_blocks_merged", "os", + "Number of merge blocks merged (innodb_os_merge_blocks_merged)", + static_cast<monitor_type_t>( + MONITOR_EXISTING | MONITOR_DEFAULT_ON), + MONITOR_DEFAULT_START, MONITOR_MERGE_BLOCKS_MERGED}, + /* ========== Counters for Transaction Module ========== */ {"module_trx", "transaction", "Transaction Manager", MONITOR_MODULE, @@ -1626,6 +1645,21 @@ srv_mon_process_existing_counter( update_min = TRUE; break; + /* innodb_os_merge_blocks_written */ + case MONITOR_MERGE_BLOCKS_WRITTEN: + value = srv_stats.merge_buffers_written; + break; + + /* innodb_os_merge_blocks_read */ + case MONITOR_MERGE_BLOCKS_READ: + value = srv_stats.merge_buffers_read; + break; + + /* innodb_os_merge_blocks_merged */ + case MONITOR_MERGE_BLOCKS_MERGED: + value = srv_stats.merge_buffers_merged; + break; + /* innodb_log_waits */ case MONITOR_OVLD_LOG_WAITS: value = srv_stats.log_waits; diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index 89dadf9f08c..b3df528f6ca 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -3,7 +3,7 @@ Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, 2009 Google Inc. Copyright (c) 2009, Percona Inc. -Copyright (c) 2013, 2014, SkySQL Ab. All Rights Reserved. +Copyright (c) 2013, 2015, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -1551,6 +1551,10 @@ srv_export_innodb_status(void) } #endif /* UNIV_DEBUG */ + export_vars.innodb_merge_buffers_written = srv_stats.merge_buffers_written; + export_vars.innodb_merge_buffers_read = srv_stats.merge_buffers_read; + export_vars.innodb_merge_buffers_merged = srv_stats.merge_buffers_merged; + mutex_exit(&srv_innodb_monitor_mutex); } diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index 4ad637d57d3..c55a260be9a 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -4,7 +4,7 @@ Copyright (c) 2000, 2015, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, 2009 Google Inc. Copyright (c) 2009, Percona Inc. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2013, 2014 SkySQL Ab. All Rights Reserved. +Copyright (c) 2013, 2015, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -824,6 +824,12 @@ static SHOW_VAR innodb_status_variables[]= { (char*) &export_vars.innodb_os_log_pending_writes, SHOW_LONG}, {"os_log_written", (char*) &export_vars.innodb_os_log_written, SHOW_LONGLONG}, + {"os_merge_buffers_written", + (char*) &export_vars.innodb_merge_buffers_written, SHOW_LONGLONG}, + {"os_merge_buffers_read", + (char*) &export_vars.innodb_merge_buffers_read, SHOW_LONGLONG}, + {"os_merge_buffers_merged", + (char*) &export_vars.innodb_merge_buffers_merged, SHOW_LONGLONG}, {"page_size", (char*) &export_vars.innodb_page_size, SHOW_LONG}, {"pages_created", diff --git a/storage/xtradb/include/srv0mon.h b/storage/xtradb/include/srv0mon.h index 2d90f47eefe..d2b65721e1a 100644 --- a/storage/xtradb/include/srv0mon.h +++ b/storage/xtradb/include/srv0mon.h @@ -2,6 +2,7 @@ Copyright (c) 2010, 2013, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. +Copyright (c) 2014, 2015, 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 @@ -255,6 +256,9 @@ enum monitor_id_t { MONITOR_OVLD_OS_LOG_FSYNC, MONITOR_OVLD_OS_LOG_PENDING_FSYNC, MONITOR_OVLD_OS_LOG_PENDING_WRITES, + MONITOR_MERGE_BLOCKS_WRITTEN, + MONITOR_MERGE_BLOCKS_READ, + MONITOR_MERGE_BLOCKS_MERGED, /* Transaction related counters */ MONITOR_MODULE_TRX, diff --git a/storage/xtradb/include/srv0srv.h b/storage/xtradb/include/srv0srv.h index 6deb8dc5584..14c9cd4de26 100644 --- a/storage/xtradb/include/srv0srv.h +++ b/storage/xtradb/include/srv0srv.h @@ -3,7 +3,7 @@ Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved. Copyright (c) 2008, 2009, Google Inc. Copyright (c) 2009, Percona Inc. -Copyright (c) 2013, 2014, SkySQL Ab. All Rights Reserved. +Copyright (c) 2013, 2015, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -145,6 +145,13 @@ struct srv_stats_t { /** Number of lock waits that have been up to max time (i.e.) lock wait timeout */ ulint_ctr_1_t n_lock_max_wait_time; + + /** Number of merge buffers written */ + ulint_ctr_64_t merge_buffers_written; + /** Number of merge buffers read */ + ulint_ctr_64_t merge_buffers_read; + /** Number of merge buffers merged */ + ulint_ctr_64_t merge_buffers_merged; }; extern const char* srv_main_thread_op_info; @@ -1088,6 +1095,9 @@ struct export_var_t{ ulint innodb_purge_view_trx_id_age; /*!< rw_max_trx_id - purged view's min trx_id */ #endif /* UNIV_DEBUG */ + ib_int64_t innodb_merge_buffers_written; + ib_int64_t innodb_merge_buffers_read; + ib_int64_t innodb_merge_buffers_merged; }; /** Thread slot in the thread table. */ diff --git a/storage/xtradb/row/row0merge.cc b/storage/xtradb/row/row0merge.cc index 0a5eb4374f1..3447d15ed1c 100644 --- a/storage/xtradb/row/row0merge.cc +++ b/storage/xtradb/row/row0merge.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2005, 2015, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2014, 2015, 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 @@ -873,6 +874,8 @@ row_merge_read( success = os_file_read_no_error_handling(OS_FILE_FROM_FD(fd), buf, ofs, srv_sort_buf_size); + srv_stats.merge_buffers_read.inc(); + #ifdef POSIX_FADV_DONTNEED /* Each block is read exactly once. Free up the file cache. */ posix_fadvise(fd, ofs, srv_sort_buf_size, POSIX_FADV_DONTNEED); @@ -907,6 +910,7 @@ row_merge_write( DBUG_EXECUTE_IF("row_merge_write_failure", return(FALSE);); ret = os_file_write("(merge)", OS_FILE_FROM_FD(fd), buf, ofs, buf_len); + srv_stats.merge_buffers_written.inc(); #ifdef UNIV_DEBUG if (row_merge_print_block_write) { @@ -1744,7 +1748,7 @@ write_buffers: /* We have enough data tuples to form a block. Sort them and write to disk. */ - if (buf->n_tuples) { + if (UNIV_LIKELY(buf->n_tuples)) { if (dict_index_is_unique(buf->index)) { row_merge_dup_t dup = { buf->index, table, col_map, 0}; @@ -1785,13 +1789,17 @@ write_buffers: dict_index_get_lock(buf->index)); } - row_merge_buf_write(buf, file, block); + /* Do not write empty buffers to temporary file */ + if (buf->n_tuples) { + + row_merge_buf_write(buf, file, block); - if (!row_merge_write(file->fd, file->offset++, - block)) { - err = DB_TEMP_FILE_WRITE_FAILURE; - trx->error_key_num = i; - break; + if (!row_merge_write(file->fd, file->offset++, + block)) { + err = DB_TEMP_FILE_WRITE_FAILURE; + trx->error_key_num = i; + break; + } } UNIV_MEM_INVALID(&block[0], srv_sort_buf_size); @@ -2076,6 +2084,9 @@ done1: mem_heap_free(heap); b2 = row_merge_write_eof(&block[2 * srv_sort_buf_size], b2, of->fd, &of->offset); + + srv_stats.merge_buffers_merged.inc(); + return(b2 ? DB_SUCCESS : DB_CORRUPTION); } @@ -3755,17 +3766,21 @@ wait_again: DEBUG_FTS_SORT_PRINT("FTS_SORT: Complete Insert\n"); #endif } else { - row_merge_dup_t dup = { - sort_idx, table, col_map, 0}; - - error = row_merge_sort( - trx, &dup, &merge_files[i], - block, &tmpfd); - - if (error == DB_SUCCESS) { - error = row_merge_insert_index_tuples( - trx->id, sort_idx, old_table, - merge_files[i].fd, block); + /* Sorting and inserting is required only if + there really is records */ + if (UNIV_LIKELY(merge_files[i].n_rec)) { + row_merge_dup_t dup = { + sort_idx, table, col_map, 0}; + + error = row_merge_sort( + trx, &dup, &merge_files[i], + block, &tmpfd); + + if (error == DB_SUCCESS) { + error = row_merge_insert_index_tuples( + trx->id, sort_idx, old_table, + merge_files[i].fd, block); + } } } diff --git a/storage/xtradb/srv/srv0mon.cc b/storage/xtradb/srv/srv0mon.cc index a0dd32c203f..960c889f871 100644 --- a/storage/xtradb/srv/srv0mon.cc +++ b/storage/xtradb/srv/srv0mon.cc @@ -2,6 +2,7 @@ Copyright (c) 2010, 2014, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. +Copyright (c) 2014, 2015, 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 @@ -674,6 +675,24 @@ static monitor_info_t innodb_counter_info[] = MONITOR_EXISTING | MONITOR_DEFAULT_ON), MONITOR_DEFAULT_START, MONITOR_OVLD_OS_LOG_PENDING_WRITES}, + {"os_merge_blocks_written", "os", + "Number of merge blocks written (innodb_os_merge_blocks_written)", + static_cast<monitor_type_t>( + MONITOR_EXISTING | MONITOR_DEFAULT_ON), + MONITOR_DEFAULT_START, MONITOR_MERGE_BLOCKS_WRITTEN}, + + {"os_merge_blocks_read", "os", + "Number of merge blocks read (innodb_os_merge_blocks_read)", + static_cast<monitor_type_t>( + MONITOR_EXISTING | MONITOR_DEFAULT_ON), + MONITOR_DEFAULT_START, MONITOR_MERGE_BLOCKS_READ}, + + {"os_merge_blocks_merged", "os", + "Number of merge blocks merged (innodb_os_merge_blocks_merged)", + static_cast<monitor_type_t>( + MONITOR_EXISTING | MONITOR_DEFAULT_ON), + MONITOR_DEFAULT_START, MONITOR_MERGE_BLOCKS_MERGED}, + /* ========== Counters for Transaction Module ========== */ {"module_trx", "transaction", "Transaction Manager", MONITOR_MODULE, @@ -1626,6 +1645,21 @@ srv_mon_process_existing_counter( update_min = TRUE; break; + /* innodb_os_merge_blocks_written */ + case MONITOR_MERGE_BLOCKS_WRITTEN: + value = srv_stats.merge_buffers_written; + break; + + /* innodb_os_merge_blocks_read */ + case MONITOR_MERGE_BLOCKS_READ: + value = srv_stats.merge_buffers_read; + break; + + /* innodb_os_merge_blocks_merged */ + case MONITOR_MERGE_BLOCKS_MERGED: + value = srv_stats.merge_buffers_merged; + break; + /* innodb_log_waits */ case MONITOR_OVLD_LOG_WAITS: value = srv_stats.log_waits; diff --git a/storage/xtradb/srv/srv0srv.cc b/storage/xtradb/srv/srv0srv.cc index e679e180d45..da293a4dd3f 100644 --- a/storage/xtradb/srv/srv0srv.cc +++ b/storage/xtradb/srv/srv0srv.cc @@ -3,7 +3,7 @@ Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, 2009 Google Inc. Copyright (c) 2009, Percona Inc. -Copyright (c) 2013, 2014, SkySQL Ab. All Rights Reserved. +Copyright (c) 2013, 2015, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -1927,6 +1927,10 @@ srv_export_innodb_status(void) } #endif /* UNIV_DEBUG */ + export_vars.innodb_merge_buffers_written = srv_stats.merge_buffers_written; + export_vars.innodb_merge_buffers_read = srv_stats.merge_buffers_read; + export_vars.innodb_merge_buffers_merged = srv_stats.merge_buffers_merged; + mutex_exit(&srv_innodb_monitor_mutex); } |