关于单线程与多线程数据库性能

Jér*_*nge 63 performance database-recommendation

H2 是一个单线程数据库,在性能方面享有盛誉。其他数据库是多线程的。

我的问题是:多线程数据库什么时候变得比单线程数据库更有趣?有多少用户?多少个进程?什么是触发器?有人有经验可以分享吗?

概括

  • 通常的瓶颈是磁盘访问
  • SSD 速度很快,但很脆弱(必须执行故障程序)
  • 单线程系统上的一个长查询将阻塞所有其他查询
  • 配置多线程系统可能很棘手
  • 即使在单核系统上,多线程数据库也是有益的

Rol*_*DBA 50

如果我可以说关于 MySQL 的一件事是 InnoDB,它的事务性(符合 ACID 的)存储引擎,确实是多线程的。但是,它与您配置的一样多线程!!!即使是“开箱即用”,在给定默认设置的情况下,InnoDB 在单个 CPU 环境中也表现出色。要利用 InnoDB 多线程功能,您必须记住激活很多选项。

innodb_thread_concurrency设置 InnoDB 可以保持打开的并发线程数的上限。为此设置的最佳整数是(2 X CPU 数)+ 磁盘数。更新:正如我从 Percona NYC 会议上第一手了解到的那样,您应该将其设置为 0,以便提醒 InnoDB 存储引擎找到适合其运行环境的最佳线程数。

innodb_concurrency_tickets设置可以绕过并发检查而不受惩罚的线程数。达到该限制后,线程并发检查再次成为常态。

innodb_commit_concurrency设置可以提交的并发事务数。由于默认值为 0,因此不设置此项将允许同时提交任意数量的事务。

innodb_thread_sleep_delay设置 InnoDB 线程在重新进入 InnoDB 队列之前可以休眠的毫秒数。默认值为 10000(10 秒)。

innodb_read_io_threadsinnodb_write_io_threads(均自 MySQL 5.1.38 起)为读取和写入分配指定数量的线程。默认值为 4,最大值为 64。

innodb_replication_delay在达到 innodb_thread_concurrency 时对从属设备施加线程延迟。

innodb_read_ahead_threshold允许在切换到异步读取之前线性读取设置的范围数(64 页 [页 = 16K])。

如果我命名更多选项,时间就会逃跑。您可以在MySQL 的文档中阅读有关它们的信息

大多数人不知道这些特性,并且对 InnoDB 只是做符合 ACID 的事务感到非常满意。如果您调整这些选项中的任何一个,则后果自负。

我使用过 MySQL 5.5 多缓冲池实例(9 个缓冲池实例中的 162GB)并尝试以这种方式在内存中自动分区数据。一些专家说这应该会给你带来 50% 的性能提升。我得到的是大量线程锁定,实际上使 InnoDB 爬行。我切换到 1 个缓冲区 (162GB),一切都恢复了正常。我想你需要 Percona 专家来设置它。明天我将参加在纽约举行的 Percona MySQL 会议,如果有机会我会询问这个问题。

总之,考虑到多线程操作的默认设置,InnoDB 现在在多 CPU 服务器中表现良好。调整它们需要非常小心、非常耐心、很好的文档和很棒的咖啡(或 Red Bull、Jolt 等)。

早安,晚安,晚安!!!

更新 2011-05-27 20:11

周四从纽约的 Percona MySQL 会议回来。什么会议。学到了很多东西,但我得到了一个关于 InnoDB 的答案。Ronald Bradford告诉我,将 innodb_thread_concurrency 设置为 0 将使 InnoDB 在内部决定线程并发性的最佳行动方案。我将在 MySQL 5.5 中进一步试验。

更新 2011-06-01 11:20

就一个长查询而言,InnoDB符合 ACID并且使用MultiVersion Concurrency Control运行得非常好。事务应该能够进行隔离级别(默认情况下可重复读取),以防止阻止其他人访问数据。

对于多核系统,InnoDB 已经走了很长一段路。过去,InnoDB 在多核环境中表现不佳。我记得必须在单个服务器上运行多个 mysql 实例才能让多个内核在 CPU 上分布多个 mysqld 进程。由于 Percona 和后来的 MySQL(呃,Oracle,说这仍然让我感到恶心),这不再是必要的,因为他们已经将 InnoDB 开发成一个更成熟的存储引擎,可以简单地访问内核而无需太多调整。今天 InnoDB 的当前实例可以在单个核心服务器中很好地运行。


Sta*_*hns 32

这是我的意见:

通常,DB 系统的瓶颈(或最慢的部分)是磁盘。CPU 仅在算术运算、处理或 CPU 执行的任何其他任务期间出现峰值。通过适当的架构,多线程可以帮助将查询的负载抵消到 CPU 上,而不是进行缓慢的磁盘读/写。在某些情况下,使用 CPU 周期计算值比创建计算列(之前保存到磁盘)并从磁盘读取该列更快。

在某些 RDBMS 中有一个临时数据库 (tempdb),该实例上的所有数据库都使用该数据库进行排序、散列、临时变量等......多线程和拆分此 tempdb 文件可用于提高 tempdb 的吞吐量,从而提高整体服务器性能。

使用多线程(并行),可以将查询的结果集拆分为在服务器的不同内核上处理,而不是单独使用一个内核。此功能并不总是能提高性能,但在某些情况下会提高性能,因此该功能可用。

DB 可用的线程有多种用途:读/写磁盘、用户连接、后台作业、锁定/闩锁、网络 IO 等......根据操作系统架构,线程被抢先馈送到 CPU 并被使用等待和队列进行管理。如果 CPU 可以很快处理这些线程,那么等待时间就会很短。多线程 DB 将比单线程 DB 更快,因为在单线程 DB 中,将有仅回收一个线程而不是其他线程可用的开销。

可伸缩性也成为一个问题,因为需要更多线程来管理和执行可伸缩的数据库系统。

  • @Jverstry ~ 是的,如果你理解这个概念,并且同意它,并且不介意重建你的整个生产环境(或者等待自动故障转移开始,然后在不久的将来的某个时候重建)然后去吧,他们会让事情变得更快,是的。 (2认同)

小智 11

一旦您有多个并发用户或进程,甚至是具有多线程数据库访问的单个进程,拥有一个支持线程的数据库就会变得很有趣。

H2 是线程安全的,但会将所有请求序列化到数据库,这在重负载场景中可能会成为潜在的性能问题。对于特定项目是否确实如此,取决于您的性能要求、访问数据库的线程/用户/进程数量、这些线程执行的查询频率以及您的平均和最坏情况下的性能的组合。查询。

例如,如果您的性能要求是在 1 秒内得到响应,并且您有不超过 10 个并发用户执行需要 0.05 秒执行的单个查询,单线程数据库仍然可以让您达到这些目标(尽管是多线程的)可能已经显着提升了性能)。考虑到具有半秒性能的单个潜在查询的相同场景,序列化您的数据库访问将不再允许您满足您的性能目标。

如果您目前在您的项目中使用 H2,我建议您在负载情况下针对您的代码库运行分析器(只需使用一些典型用例启动 x 数量的线程同时命中您的代码)。这将为您提供有关代码库中性能和瓶颈的实际指标,而不仅仅是理论化。如果这表明您的请求花费了大部分时间只是在等待访问数据库,则是时候转移到线程数据库了。


Jac*_*las 8

据我所知,“单线程”对于 H2 来说有点用词不当。关键是它序列化所有事务(即一次执行一个)。

关于这对您的应用程序是否“正常”的关键问题不是“有多少用户?” 甚至“有多少流程?”,而是“我的交易需要多长时间?”

如果您所有的交易都是亚秒级的,这可能没问题,如果有些交易需要几个小时才能完成,那可能不太好,因为所有其他待处理的交易都在等待它们完成。关于这是否“好”的决定将取决于您自己的性能要求 - 即我的用户通过事务访问数据库的可接受等待时间。

- 编辑

似乎 H2 并没有真正序列化事务——只是 DML。换句话说,单个长事务中的大量短更新不会阻止其他更新。但是,除非您使用实验性 MVCC 功能,否则表锁定意味着这在实践中具有类似的效果。还有一个实验性的“multi_threaded”功能,但它不能与 MVCC 同时使用


Den*_*rdy 5

引用 PostgreSQL 网站上的点点滴滴……请注意,我完全不知道这些论点的优点——它们只是不适合评论。

来自开发人员常见问题解答(“为什么不使用线程......”):

http://wiki.postgresql.org/wiki/Developer_FAQ#Why_don.27t_you_use_threads.2C_raw_devices.2C_async-I.2FO.2C_.3Cinsert_your_favorite_wizz-bang_feature_here.3E.3F

当前不使用线程代替后端的多个进程,因为:(...)

  • 如果某个后端是单个进程中的线程,则一个后端中的错误可能会损坏其他后端
  • 与剩余的后端启动时间相比,使用线程的速度提升很小。
  • 只读可执行映射的共享和 shared_buffers 的使用意味着进程(如线程)的内存效率非常高
  • 定期创建和销毁进程有助于防止内存碎片,这在长时间运行的进程中很难管理

从 Todo 列表(“我们不想要的功能”):

http://wiki.postgresql.org/wiki/Todo#Features_We_Do_Not_Want

所有后端在单个进程中作为线程运行(不需要)

这消除了我们从当前设置中获得的过程保护。在现代系统上,线程创建的开销通常与进程创建的开销相同,因此使用纯线程模型似乎是不明智的,而且 MySQL 和 DB2 已经证明,线程引入的问题与它们解决的问题一样多。(……)

所以,再次......我完全不知道上述优点。只是太长了,不适合发表评论。