与MyISAM相比,为什么TokuDB和InnoDB插入速度太慢

时间:2014-02-18 19:45:14

标签: mysql innodb myisam mariadb tokudb

我准备了以下SQL语句来比较MyISAM,InnoDB和TokuDB的性能行为(INSERT执行100000次):

的MyISAM:

CREATE TABLE `testtable_myisam` (`id` bigint(20) NOT NULL AUTO_INCREMENT, `value1` INT DEFAULT NULL, `value2` INT DEFAULT NULL, PRIMARY KEY (`id`), KEY `index1` (`value1`)) ENGINE=MyISAM DEFAULT CHARSET=utf8;

INSERT INTO `testtable_myisam` (`value1`, `value2`) VALUES (FLOOR(RAND() * 1000), FLOOR(RAND() * 1000)); 

InnoDB的:

CREATE TABLE `testtable_innodb` (`id` bigint(20) NOT NULL AUTO_INCREMENT, `value1` INT DEFAULT NULL, `value2` INT DEFAULT NULL, PRIMARY KEY (`id`), KEY `index1` (`value1`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO `testtable_innodb` (`value1`, `value2`) VALUES (FLOOR(RAND() * 1000), FLOOR(RAND() * 1000));

TokuDB:

CREATE TABLE `testtable_tokudb` (`id` bigint(20) NOT NULL AUTO_INCREMENT, `value1` INT DEFAULT NULL, `value2` INT DEFAULT NULL, PRIMARY KEY (`id`), KEY `index1` (`value1`)) ENGINE=TokuDB DEFAULT CHARSET=utf8;

INSERT INTO `testtable_tokudb` (`value1`, `value2`) VALUES (FLOOR(RAND() * 1000), FLOOR(RAND() * 1000));

最初,InnoDB的INSERT性能比MyISAM慢近50倍,而TokuDB比MyISAM慢40倍。

然后我在InnoDB上找出“innodb-flush-log-at-trx-commit = 2”的设置,使其INSERT行为与MyISAM类似。

问题是,我应该在TokuDB上做什么?我敢打赌,TokuDB的糟糕的INSERT性能也是由一些不正确的设置引起的,但我无法弄清楚原因。

---------更新---------

感谢tmcallaghan的评论,我已将我的设置修改为“tokudb_commit_sync = OFF”,现在TokuDB在小数据集上的插入率似乎是有意义的(一旦我发现以下问题,我将在大型数据集上执行它们):

然而,与具有以下SQL的MyISAM和InnoDB相比,TokuDB的选择性能仍然是有线的(其中?由我的模拟器替换为不同的Int):

SELECT id, value1, value2 FROM testtable_myisam WHERE value1=?; 
SELECT id, value1, value2 FROM testtable_innodb WHERE value1=?; 
SELECT id, value1, value2 FROM testtable_tokudb WHERE value1=?; 

在一百万个数据集上,MyISAM和InnoDB各自的每个10k SELECT语句花费10和15秒,但TokuDB需要大约40秒。

我是否错过了其他一些设置?

提前致谢!

3 个答案:

答案 0 :(得分:4)

这听起来不是一个非常有趣的测试(100,000行不是很多,而且你的插入不是并发的),但这里是你要找的设置。

发出“set tokudb_commit_sync = 0;”将在提交操作上关闭fsync()。请注意,此模式下没有耐久性保证。

正如我前面提到的,TokuDB的优势在于索引的数据明显大于RAM,而且这个测试不是。

答案 1 :(得分:3)

事务引擎较慢的原因是它们强制硬盘确认它写下数据。为了使HDD向下写入数据,必须将磁头定位在磁盘板上并流式传输数据。每个事务意味着磁盘将磁针定位在磁头上,向下写入数据并告诉操作系统确保它在那里。

事务引擎这样做的原因是它们可以符合ACID的D部分。它们确保您希望记录下来的数据,实际上是永久记录下来的。 MyISAM不这样做。

因此,插入速度与硬盘的每秒输入输出操作数(IOPS)成比例。 这也意味着,如果您在一个事务中包装多个查询,则可以利用所述驱动器的写入速度带宽。 此外,这意味着具有高IOPS的驱动器(例如,SSD具有40,000多IOPS,机械驱动器具有大约250-300的范围,但是我不会用我的话来说明确切的数字)。

简而言之,如果您希望使用事务引擎实现快速插入 - 在单个事务中包装多个查询。 你所做的所有“优化”都略微违反了ACID的D部分,因为引擎会尝试利用可以用作缓冲区的各种快速存储器。这意味着,如果出现问题,例如你失去了力量 - 亲吻你的数据再见。

此外,您进行的测试实际上是不好的,因为它们是小规模的。 InnoDB和特别是TokuDB都设计为包含数百GB的数据并提供线性性能。

答案 2 :(得分:0)

我已将my.cnf更新为以下内容,现在整体表现看起来更好。

对于MyISAM的10k次SELECT,需要4秒,因此InnoDB需要5秒,而TokuDB需要8秒。因此,我可以在下面的配置中得出结论,TokuDB与MyISAM和InnoDB的行为相似(甚至没有必要更好)。

确实,我很好奇InnoDB v.s之间的大量性能比较。 TokuDB,但不是MyISAM vs.s. TokuDB,为什么?


tokudb_commit_sync=0

max_allowed_packet = 1M
table_open_cache = 128
read_buffer_size = 2M
read_rnd_buffer_size = 8M
myisam_sort_buffer_size = 64M
thread_cache_size = 8
query_cache_size = 32M
thread_concurrency = 8

innodb_flush_log_at_trx_commit=2
innodb_buffer_pool_size = 2G
innodb_additional_mem_pool_size = 20M
innodb_log_buffer_size = 8M
innodb_lock_wait_timeout = 50