MYSQL 大数据库中插入和更新缓慢

MYSQL Slow Insertion and Update in Big Database

我在调整 mysql 配置以最大化插入和更新查询的速度时遇到问题。

当我们每天必须插入每天大约 50 万条记录的数据时,就会出现问题,并且它会 运行 几分钟才能完成。

在它执行作业时,我检查并发现它使用的 CPU 不到 5% 和一半的内存。我的问题是如何通过最大化 mysql 来使用所有可用资源来提高速度。

谢谢。

性能
Insert/Update 在 MyISAM 和 InnoDB 表上每秒大约有 2,000-4,000 条记录

Table#1
引擎:MyISAM
列数:21
现有行:5,400,000
键:7 列上的一个唯一键和一个主键

Table#2
引擎:InnoDD
列数:14
现有行:1,500,000
键:一个主键,一个 6 列上的唯一键,两个索引

插入方法

LOAD DATA LOCAL INFILE

硬件规格

    2 x Intel Xeon E5-2640v2 2.1GHz, 20M Cache, 7.2GT/s
    RAM 16GB
    2 x HDD 300GB 15K RPM,6Gbps SAS 2.5

my.cnf配置

[mysqld]
local-infile=1
max_connections = 600
max_user_connections=1000
key_buffer_size = 3584M
myisam_sort_buffer_size = 64M
read_buffer_size = 256K
table_open_cache = 5000
thread_cache_size = 384
wait_timeout = 20
connect_timeout = 10
tmp_table_size = 256M
max_heap_table_size = 128M
max_allowed_packet=268435456
net_buffer_length = 16384
max_connect_errors = 10
concurrent_insert = 2
read_rnd_buffer_size = 786432
bulk_insert_buffer_size = 8M
query_cache_limit = 5M
query_cache_size = 1024M
query_cache_type = 1
query_prealloc_size = 262144
query_alloc_block_size = 65535
transaction_alloc_block_size = 8192
transaction_prealloc_size = 4096
max_write_lock_count = 8
log-error
external-locking=FALSE
open_files_limit=50000
#expire-logs-days = 7

innodb_buffer_pool_size = 2024M
innodb_log_buffer_size = 8M
innodb_thread_concurrency = 0
innodb_read_io_threads = 64
innodb_write_io_threads = 64
innodb_log_file_size = 64M
innodb_flush_method = O_DIRECT

sort_buffer_size = 512K
read_rnd_buffer_size = 1M
tmp_table_size = 1G
max_heap_table_size = 512M


[mysqld_safe]

[mysqldump]
quick
max_allowed_packet = 16M

[isamchk]
key_buffer = 384M
sort_buffer = 384M
read_buffer = 256M
write_buffer = 256M

[myisamchk]
key_buffer = 384M
sort_buffer = 384M
read_buffer = 256M
write_buffer = 256M

#### Per connection configuration ####
sort_buffer_size = 1M
join_buffer_size = 1M
thread_stack = 192K

MysqlTuner 结果

-------- Storage Engine Statistics -------------------------------------------
[--] Status: +ARCHIVE +BLACKHOLE +CSV -FEDERATED +InnoDB +MRG_MYISAM 
[--] Data in MyISAM tables: 5G (Tables: 306)
[--] Data in InnoDB tables: 269M (Tables: 441)
[--] Data in PERFORMANCE_SCHEMA tables: 0B (Tables: 52)
[!!] Total fragmented tables: 34

-------- Security Recommendations  -------------------------------------------
[OK] All database users have passwords assigned

-------- Performance Metrics -------------------------------------------------
[--] Up for: 1d 12h 58m 9s (4M q [37.247 qps], 70K conn, TX: 21B, RX: 1B)
[--] Reads / Writes: 67% / 33%
[--] Total buffers: 7.0G global + 2.2M per thread (600 max threads)
[OK] Maximum possible memory usage: 8.3G (53% of installed RAM)
[OK] Slow queries: 0% (72/4M)
[OK] Highest usage of available connections: 2% (15/600)
[OK] Key buffer size / total MyISAM indexes: 3.5G/1.5G
[OK] Key buffer hit rate: 99.6% (304M cached / 1M reads)
[OK] Query cache efficiency: 97.0% (3M cached / 3M selects)
[OK] Query cache prunes per day: 11
[!!] Sorts requiring temporary tables: 14% (1K temp sorts / 9K sorts)
[!!] Temporary tables created on disk: 28% (1K on disk / 4K total)
[OK] Thread cache hit rate: 99% (15 created / 70K connections)
[OK] Table cache hit rate: 74% (1K open / 1K opened)
[OK] Open file limit used: 1% (831/50K)
[OK] Table locks acquired immediately: 99% (755K immediate / 755K locks)
[OK] InnoDB buffer pool / data size: 2.0G/269.9M
[OK] InnoDB log waits: 0
-------- Recommendations -----------------------------------------------------
General recommendations:
    Run OPTIMIZE TABLE to defragment tables for better performance
    Temporary table size is already large - reduce result set size
    Reduce your SELECT DISTINCT queries without LIMIT clauses
Variables to adjust:
    sort_buffer_size (> 512K)
    read_rnd_buffer_size (> 1M)

query_cache_size = 1024M query_cache_type = 1

那些不好。每次您向 table 写入内容时,查询缓存都需要删除对 table 的所有引用。 1G 很多太大了; 50M是我推荐的。此外,除非您已证明需要查询缓存,否则我建议将其关闭。

另一方面,"Query cache efficiency: 97.0% (3M cached / 3M selects)"说你用的是QC,是有效的。所以也许你应该保留它,但缩小尺寸。

至于加载 -- 你是 'replacing' table 吗?或者添加到 table。如果要替换,则加载到新的 table,然后重命名 TABLE 以将其放置到位。

tmp_table_size = 1G max_heap_table_size = 512M

这些都非常危险。如果多个线程同时需要 tmp tables,您可能 运行 内存不足。将它们恢复为默认值。

"Temporary tables created on disk: 28%" 不一定能通过增加这些设置得到改善。如果有 TEXT 或 BLOB 列,tmp tables 将转到磁盘。如果您愿意,请向我们展示 SHOW CREATE TABLE 和调皮的 SELECT。

"Run OPTIMIZE TABLE to defragment tables for better performance" -- 该工具总是这么说。这几乎总是虚假的建议。

您是否仅通过加载数据加载?您还提到了更新;请详细说明。

“CPU 的 5%”-- 你有多少 'cores'?请记住,一个 MySQL 连接将仅使用一个 CPU 核心。

"half of memory" -- 这是假的。 MyISAM 使用另一半的一部分来缓存数据。没有别的可以利用 space.

这是一个潜在的优化(对于加载数据):在执行加载数据之前按主键对数据进行排序。请提供 SHOW CREATE TABLE;在这方面可能会有进一步的提示。

您是否删除了 'old' 数据?那是基于时间的吗?如果是这样,让我们​​谈谈分区。