【问题标题】:Why TokuDB and InnoDB insert is so slow compared to MyISAM为什么 TokuDB 和 InnoDB 插入比 MyISAM 慢
【发布时间】:2014-02-18 19:45:14
【问题描述】:

我准备了以下 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 的 cmets,我已将我的设置修改为“tokudb_commit_sync=OFF”,现在 TokuDB 在小数据集上的插入率似乎很有意义(一旦我发现以下问题,我将在大数据集上执行它们):

但是,与 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 和 15 秒的每 10k SELECT 语句,但 TokuDB 需要大约 40 秒。

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

提前致谢!

【问题讨论】:

  • 离题。不是编程问题。这是更多的数据库配置/调整。请尝试使用 DBA 站点。
  • 设置 unique_checks=off; ??

标签: mysql innodb myisam mariadb tokudb


【解决方案1】:

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

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

正如我之前提到的,TokuDB 的优势在于索引数据明显大于 RAM,而本次测试并非如此。

【讨论】:

  • 嗨 tmcallaghan,感谢 cmets。真正的1000000不是什么系列,我把这个作为第一个测试只是为了确保以上所有引擎都有相当的性能,之后我会推出一些更复杂的表结构和数十亿行的大测试。
  • 那么你就得到了答案,MyISAM 在你的测试中是最快的,只有很少的数据。实际上,您当前测量的所有测试都是存储系统的 fsync() 性能。包含复杂表和数十亿行的“大型测试”将显示截然不同的结果。
  • 正如编辑后的帖子中所写,tokudb_commit_sync 确实有助于提高插入率,谢谢!但是查询性能仍然比 MyISAM 和 InnoDB 慢很多(大约慢 3 倍)在 100 万个数据库上。我又错过了什么(即使数据库规模很小)?
  • 同样,一百万行并不多,查询延迟取决于许多因素。我一直在帮助人们进行评估,创建足够的数据来模拟您的真实用例,否则测试结果并不重要。
【解决方案2】:

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

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

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

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

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

【讨论】:

  • 这是非常好的信息,解决了我关于 MyISAM 和 InnoDB 之间速度差异的问题,非常感谢!正如我刚刚发布的评论,现在我对插入速度很清楚,但仍然不明白为什么 InnoDB 和 TokuDB 的选择较慢,尤其是为什么 TokuDB 的选择几乎是 MyISAM 的两倍。我的意思是在更大的数据集(10m-100m)上运行模拟,希望能得到不同的结果。
  • 使用 TokuDB 中的聚集索引和 InnoDB 中的主键来衡量选择。通过增加变量innodb_buffer_pool 确保 InnoDB 有足够的可用 RAM。 100m 并不是很大,我有大约 50gb 的 InnoDB 正在生产中,而且我看到 TB 级的 InnoDB 数据集运行速度非常快。
【解决方案3】:

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

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

确实,我对 InnoDB 与 InnoDB 之间的大量性能比较感到好奇。 TokuDB,但不是 MyISAM v.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

【讨论】:

    猜你喜欢
    • 2016-10-06
    • 1970-01-01
    • 2011-09-27
    • 1970-01-01
    • 2011-10-17
    • 2011-04-18
    • 1970-01-01
    • 1970-01-01
    • 2012-09-18
    相关资源
    最近更新 更多