插入到下表中需要70秒才能完成:
CREATE TABLE IF NOT EXISTS `productsCategories` ( `categoriesId` int(11) NOT NULL, `productsId` int(11) NOT NULL, PRIMARY KEY (`categoriesId`,`productsId`), KEY `categoriesId` (`categoriesId`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
表中有大约10万行,磁盘占用7MB。
MySQL中有一些可以提高写入性能的设置吗?
我的my.cnf文件如下:
log-slow-queries="/var/log/mysql/slow-query.log" long_query_time=1 log-queries-not-using-indexes innodb_buffer_pool_size=4G innodb_log_buffer_size=4M innodb_flush_log_at_trx_commit=2 innodb_thread_concurrency=8 innodb_flush_method=O_DIRECT query_cache_size = 6G key_buffer_size = 284M query_cache_limit = 1024M thread_cache_size = 128 table_cache = 12800 sort_buffer_size=2M read_rnd_buffer_size = 8M myisam_sort_buffer_size = 64M read_buffer_size=128K open_files_limit = 1000 table_definition_cache = 1024 table_open_cache = 6000 max_heap_table_size=512M tmp_table_size=4096M max_connections=1000 thread_concurrency = 24
这里是硬件设置:
鉴于这个硬件,我不希望这个问题成为硬件瓶颈。
首先吸引我眼球的是桌子结构
CREATE TABLE IF NOT EXISTS `productsCategories` ( `categoriesId` int(11) NOT NULL, `productsId` int(11) NOT NULL, PRIMARY KEY (`categoriesId`,`productsId`), KEY `categoriesId` (`categoriesId`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
请注意categoriesId索引和PRIMARY KEY从同一列开始。 这是一个多余的指标。 由于这个表是InnoDB,所以categoriesId索引是多余的,因为另一个原因:所有二级索引都包含gen_clust_index(aka集群索引;请参阅在mysql中使用的gen_clust_index是什么?
如果您删除categoriesId索引
ALTER TABLE productsCategories DROP INDEX categoriesId;
这将显着提高INSERT ,因为不必执行额外的Secondary和Clustered索引维护。
如果您正在执行任何批量插入操作,则需要大容量插入缓冲区 。
请看看我以前的post:
你的日志文件太小了! 它应该是InnoDB缓冲池的25%,在你的情况下应该是1G。 查看我的文章,了解如何调整InnoDB日志文件的大小 。
请不要设置innodb_thread_concurrency !!! 我在Percona Live NYC第一时间亲自了解了这个设置 。 它在MySQL 5.5,MySQL 5.1 InnoDB Plugin和Percona Server 5.1+中默认是禁用的。
你需要使用innodb_file_per_table。 如果这是禁用的,我把ibdata1上的文件维护一个噩梦。 请阅读我的post,关于如何清理InnoDB来实现这一点 。
如果您使用MySQL 5.5或Percona Server,则必须设置某些选项才能使InnoDB使用多个CPU /多个内核。 请在这些设置上看到我的post 。
你有innodb_log_buffer_size=4M 。 默认值是8M。 这将导致重做日志的两倍。 这也会抵消你的innodb_flush_log_at_trx_commit=2设置。 请设置为32M。 另请参阅innodb_log_buffer_size上的MySQL文档 。
鉴于这些意见,请添加或更换以下设置:
[mysqld] innodb_thread_concurrency = 0 innodb_read_io_threads = 64 innodb_write_io_threads = 64 innodb_io_capacity = 5000 innodb_file_per_table innodb_log_file_size=1G innodb_log_buffer_size=1G bulk_insert_buffer_size = 256M
您应该检查innodb_log_file_size ,默认设置是5M,对于写入密集型设置而言是相当低的。 考虑将其设置为100M。 您必须删除旧的ib_logfile*文件才能使用新的设置启动数据库。 请不要在数据库服务器运行时删除日志文件,您必须先停止它。 可能你应该先备份旧的日志文件,而不是删除它们。