1

我准备了以下 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));

托库数据库:

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 在小数据集上的插入率似乎很有意义(一旦我发现以下问题,我将在大数据集上执行它们):

然而,与 MyISAM 和 InnoDB 相比,TokuDB 的选择性能仍然是有线的,具有以下 SQL(其中 ? 被我的模拟器替换为不同的 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 和 15 秒的每 10k SELECT 语句,但 TokuDB 需要大约 40 秒。

我错过了其他一些设置吗?

提前致谢!

4

3 回答 3

4

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

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

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

于 2014-02-18T20:56:08.203 回答
3

事务引擎速度较慢的原因是它们强制硬盘确认它已将数据写下来。为了让 HDD 写下数据,它必须将磁头定位在磁盘板上并流式传输数据。每笔交易都意味着磁盘将磁针定位在磁头上方,写下数据并告诉操作系统它确实存在。

事务引擎这样做的原因是它们可以符合 ACID 的 D 部分。他们确保您想要写下的数据实际上是永久写下的。MyISAM 不这样做。

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

长话短说,如果您想使用事务引擎进行真正快速的插入 - 将多个查询包装在一个事务中。您所做的所有“优化”都略微违反了 ACID 的 D 部分,因为引擎将尝试利用可用作缓冲区的各种快速内存。这意味着,如果出现问题,例如您断电,请与您的数据告别。

此外,您进行的测试实际上很糟糕,因为它们的规模很小。InnoDB 尤其是 TokuDB 都旨在包含数百 GB 的数据并提供线性性能。

于 2014-02-19T14:56:04.777 回答
0

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

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

事实上,我很好奇 InnoDB 与 TokuDB 之间的大量性能比较,但不是 MyISAM 与 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
于 2014-02-19T14:46:06.010 回答