【问题标题】:Delete and Insert takes long time in MySQL(InnoDB)在 MySQL(InnoDB) 中删除和插入需要很长时间
【发布时间】:2016-01-17 15:54:13
【问题描述】:

我已经设置了一组数字,其中的每个数字都有几个与之相关的数字。所以我将它存储在这样的表中:

NUMBERS  ASSOCIATEDNUMBERS
1        3
1        7
1        8
2        11
2        7
7        9
8        13
11       17
14       18
17       11
17       18

因此,它是一个有许多相关数字的数字,反之亦然。两列都有索引。 (从而使我能够找到数字及其相关数字,反之亦然)

我的创建表如下所示:

CREATE TABLE `TABLE_B` (
  `NUMBERS` bigint(20) unsigned NOT NULL,
  `ASSOCIATEDNUMBERS` bigint(20) unsigned NOT NULL,
  UNIQUE KEY `unique_number_associatednumber_constraint` (`NUMBERS`,`ASSOCIATEDNUMBERS`),
  KEY `fk_AssociatedNumberConstraint` (`ASSOCIATEDNUMBERS`),
  CONSTRAINT `fk_AssociatedNumberConstraint` FOREIGN KEY (`ASSOCIATEDNUMBERS`) REFERENCES `table_a` (`SRNO`),
  CONSTRAINT `fk_NumberConstraint` FOREIGN KEY (`NUMBERS`) REFERENCES `table_a`` (`SRNO`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

这里TABLE_A 的列SRNOAUTO_INCREMENT PRIMARY KEY,并且是表中的第一个 列。 (根据 MySQL 手册,我没有在 TABLE_B.NUMBERSTABLE_B.ASSOCIATEDNUMBERS 上定义索引,因为外键约束会自动定义它)

问题:

每当我需要将ASSOCIATEDNUMBERS 更改为一个数字(在“NUMBERS”中)时,我只需从表中删除该数字的现有行:

DELETE FROM TABLE_B WHERE NUMBERS= ?

然后为新的 ASSOCIATEDNUMBERS 集插入行:

INSERT INTO TABLE_B (NUMBERS, ASSOCIATEDNUMBERS) VALUES ( ?, ?), (?, ?), (?, ?), ...

但是,这需要很长时间。特别是在我的多线程应用程序中,我打开到数据库的多个连接(每个线程每个),每个连接都运行在两个查询之上(但每个查询的编号不同)。

例如,如果我打开 40 个连接,每个连接删除现有的并插入 250 个新的关联号码,最多需要 10 到 15 秒。如果我增加连接数,时间也会增加。

其他信息:

SHOW GLOBAL STATUS LIKE 'Threads_running';

最多显示 40 个线程。

Innodb 参数:

innodb_adaptive_flushing, ON
innodb_adaptive_flushing_lwm, 10
innodb_adaptive_hash_index, ON
innodb_adaptive_max_sleep_delay, 150000
innodb_additional_mem_pool_size, 2097152
innodb_api_bk_commit_interval, 5
innodb_api_disable_rowlock, OFF
innodb_api_enable_binlog, OFF
innodb_api_enable_mdl, OFF
innodb_api_trx_level, 0
innodb_autoextend_increment, 64
innodb_autoinc_lock_mode, 1
innodb_buffer_pool_dump_at_shutdown, OFF
innodb_buffer_pool_dump_now, OFF
innodb_buffer_pool_filename, ib_buffer_pool
innodb_buffer_pool_instances, 8
innodb_buffer_pool_load_abort, OFF
innodb_buffer_pool_load_at_startup, OFF
innodb_buffer_pool_load_now, OFF
innodb_buffer_pool_size, 1073741824
innodb_change_buffer_max_size, 25
innodb_change_buffering, all
innodb_checksum_algorithm, crc32
innodb_checksums, ON
innodb_cmp_per_index_enabled, OFF
innodb_commit_concurrency, 0
innodb_compression_failure_threshold_pct, 5
innodb_compression_level, 6
innodb_compression_pad_pct_max, 50
innodb_concurrency_tickets, 5000
innodb_data_file_path, ibdata1:12M:autoextend
innodb_data_home_dir, 
innodb_disable_sort_file_cache, OFF
innodb_doublewrite, ON
innodb_fast_shutdown, 1
innodb_file_format, Antelope
innodb_file_format_check, ON
innodb_file_format_max, Antelope
innodb_file_per_table, ON
innodb_flush_log_at_timeout, 1
innodb_flush_log_at_trx_commit, 2
innodb_flush_method, normal
innodb_flush_neighbors, 1
innodb_flushing_avg_loops, 30
innodb_force_load_corrupted, OFF
innodb_force_recovery, 0
innodb_ft_aux_table, 
innodb_ft_cache_size, 8000000
innodb_ft_enable_diag_print, OFF
innodb_ft_enable_stopword, ON
innodb_ft_max_token_size, 84
innodb_ft_min_token_size, 3
innodb_ft_num_word_optimize, 2000
innodb_ft_result_cache_limit, 2000000000
innodb_ft_server_stopword_table, 
innodb_ft_sort_pll_degree, 2
innodb_ft_total_cache_size, 640000000
innodb_ft_user_stopword_table, 
innodb_io_capacity, 200
innodb_io_capacity_max, 2000
innodb_large_prefix, OFF
innodb_lock_wait_timeout, 50
innodb_locks_unsafe_for_binlog, OFF
innodb_log_buffer_size, 268435456
innodb_log_compressed_pages, ON
innodb_log_file_size, 262144000
innodb_log_files_in_group, 2
innodb_log_group_home_dir, .\
innodb_lru_scan_depth, 1024
innodb_max_dirty_pages_pct, 75
innodb_max_dirty_pages_pct_lwm, 0
innodb_max_purge_lag, 0
innodb_max_purge_lag_delay, 0
innodb_mirrored_log_groups, 1
innodb_monitor_disable, 
innodb_monitor_enable, 
innodb_monitor_reset, 
innodb_monitor_reset_all, 
innodb_old_blocks_pct, 37
innodb_old_blocks_time, 1000
innodb_online_alter_log_max_size, 134217728
innodb_open_files, 300
innodb_optimize_fulltext_only, OFF
innodb_page_size, 16384
innodb_print_all_deadlocks, OFF
innodb_purge_batch_size, 300
innodb_purge_threads, 1
innodb_random_read_ahead, OFF
innodb_read_ahead_threshold, 56
innodb_read_io_threads, 64
innodb_read_only, OFF
innodb_replication_delay, 0
innodb_rollback_on_timeout, OFF
innodb_rollback_segments, 128
innodb_sort_buffer_size, 1048576
innodb_spin_wait_delay, 6
innodb_stats_auto_recalc, ON
innodb_stats_method, nulls_equal
innodb_stats_on_metadata, OFF
innodb_stats_persistent, ON
innodb_stats_persistent_sample_pages, 20
innodb_stats_sample_pages, 8
innodb_stats_transient_sample_pages, 8
innodb_status_output, OFF
innodb_status_output_locks, OFF
innodb_strict_mode, OFF
innodb_support_xa, ON
innodb_sync_array_size, 1
innodb_sync_spin_loops, 30
innodb_table_locks, ON
innodb_thread_concurrency, 0
innodb_thread_sleep_delay, 10000
innodb_undo_directory, .
innodb_undo_logs, 128
innodb_undo_tablespaces, 0
innodb_use_native_aio, OFF
innodb_use_sys_malloc, ON
innodb_version, 5.6.28
innodb_write_io_threads, 16

更新:

这里是“SHOW ENGINE InnoDB STATUS”输出:http://pastebin.com/raw/E3rK4Pu5

更新 2:

这背后的原因是其他地方,而不是真正的 DB。我的代码中的一些其他功能正在消耗大量 CPU,导致 MySQL(在同一台机器上运行)运行缓慢。感谢您的所有回答和帮助。

【问题讨论】:

  • 桌子有多大?你需要BIGINT吗?或者INT UNSIGNED 就足够了?
  • 如果你只运行 5 个线程,它的运行速度有多快?
  • 请提供SHOW ENGINE InnoDB STATUS
  • 您真的需要 FK 吗?他们确实需要额外的时间。
  • 7 倍多的线程花费了超过 7 倍的时间——这表明(信号量等待也是如此)InnoDB 正在绊倒自己。 (唉,我不明白为什么。)使用更少的线程来加快进程。

标签: mysql database innodb database-performance query-performance


【解决方案1】:

您似乎在删除/插入之前获得了对行/表的锁定,这就是它导致您出现问题的原因。

检查

SELECT * from information_schema.GLOBAL_VARIABLES;

另外,检查表上的锁使用

SHOW OPEN TABLES  from <database name> where In_use>0

和锁类型使用

SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS

因此,当您运行查询时,请在手表上添加这些内容,您还可以使用 tee 命令将其存储在文件中。

所以,还有一件事会导致这种情况,虽然你已经对列进行了索引,但是如果数据读取this 限制,mysql 会有限制。

阅读本文以安装 watch http://osxdaily.com/2010/08/22/install-watch-command-on-os-x/ 并以 1 秒的时间延迟运行 watch 脚本,然后在 watch 中运行 mysql 查询,如果要将其存储在文件中,请使用 tee 命令,然后将输出写入文件。你可以tail来获取文件中的数据

【讨论】:

  • 感谢您提供此信息。想在每次删除/插入之前在单个 txt 文件中获取这些输出,以便我了解表/行是否被锁定。但不确定如何通过应用程序运行它。没有关于如何通过应用程序(不是从命令行)使用 Tee 的信息。 “选择”输出可以使用into outfile 转移到 txt 文件,但有一些限制(比如它不能使用相同的文本文件来追加),也不能以同样的方式将 SHOW OPEN TABLES 输出转移到文件。
  • 因此,当应用程序在多个线程(连接)中删除/插入行时,我经常通过命令行运行这些查询。但只有show open tables 返回的行偶尔会显示table_b 的锁数(在in_use 列下)。但是那些特定行(被删除/插入)的锁是预期的,不是吗?或(我是否错误地解释它?)。但是,SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS 从未返回任何行。
猜你喜欢
  • 1970-01-01
  • 2015-03-31
  • 2014-02-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-07
  • 2019-11-20
相关资源
最近更新 更多