H2是在性能方面享有良好声誉的单线程数据库。其他数据库是多线程的。

我的问题是:多线程数据库什么时候比单线程数据库更有趣?有多少用户?多少个过程?触发因素是什么?任何人都有经验可以分享吗?

摘要


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


评论

就我所知,线程就此问题而言是“线程或进程”的意思-例如,postgres不是多线程的,但问题不是试图将(H2,postgres)与(Oracle,SQL Server等)进行比较/>

#1 楼

我的意见是:通常,数据库系统的瓶颈(或最慢的部分)是磁盘。 CPU仅在算术运算,处理或CPU执行的任何其他任务期间出现峰值。通过适当的体系结构,多线程可以帮助抵消查询在CPU上的负载,而不是进行慢速的磁盘读/写操作。在某些情况下,使用CPU周期来计算值要快于创建一个计算列(该记录先前已保存到磁盘)并从磁盘读取此列要快得多。

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

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

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

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

评论


感谢您的见解。我听到人们称赞固态硬盘。我想在确保查询编写正确并且应用程序合理并行之后,对这些进行投资可能是最好的选择。

–JérômeVerstrynge
2011年5月26日16:06

@Stan-在这种情况下,我认为多线程的含义有所不同,即,所有事务都按Luke的回答所述进行了序列化。

–杰克·道格拉斯(Jack Douglas)
11年5月26日在19:09

@JVerstry〜不,不是。阅读Jeff Atwood关于SSD的想法...它们的故障率很高。最好的办法是正确索引数据并进行正确编写的查询。

– jcolebrand♦
2011年5月26日19:16

@jcolebrand好吧,他似乎只通过强大的备份系统来提倡它们提高速度,以防止它们失败。

–JérômeVerstrynge
2011年5月26日19:24



@Jverstry〜是的,如果您了解该概念并且对此表示满意,并且不介意重建整个生产环境(或等待自动故障转移开始,然后在不久的将来重建),那么去做,他们会让事情变得更快,是的。

– jcolebrand♦
2011年5月26日19:29

#2 楼

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

innodb_thread_concurrency设置InnoDB可以保持打开状态的并发线程数的上限。为此设置的最佳轮数是(2 X CPU数量)+磁盘数量。更新:正如我从Percona NYC大会上第一手了解到的那样,您应该将其设置为0,以提醒InnoDB Storage Engine为正在运行的环境找到最佳的线程数。

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

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

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

innodb_read_io_threads和innodb_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操作的默认设置下的表现,它现在在多CPU服务器中表现良好。 。调整它们需要格外小心,极大的耐心,优质的文档和优质的咖啡(或Red Bull,Jolt等)。

早上好,晚上好,晚上好!!!

UPDATE 2011-05-27 20:11

周四从纽约Percona MySQL大会上回来。真是个会议。学到了很多东西,但是我得到了一个有关InnoDB的答案。 Ronald Bradford告诉我,将innodb_thread_concurrency设置为0将使InnoDB通过线程并发在内部决定最佳的操作过程。我将在MySQL 5.5中对此进行进一步的试验。

UPDATE 2011-06-01 11:20使用MultiVersion并发控制效果很好。事务应该能够带有隔离级别(默认情况下为可重复读取),以防止阻止其他人访问数据。

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

#3 楼

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

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

例如,如果您的性能要求是在一秒钟之内得到响应,那么您执行一次查询所需的并发用户数不超过10个,而执行一次查询需要花费0.05秒的时间,因此单线程数据库将仍然可以让您实现这些目标(尽管多线程可能已经明显提高了性能)。在相同的情况下,如果使用单个潜在查询,但在最坏情况下的性能只有半秒钟,序列化数据库访问将不再使您达到性能目标。

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

评论


H2会序列化所有请求-还是仅序列化DML?

–杰克·道格拉斯(Jack Douglas)
2011年5月27日4:05

#4 楼

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

关于您的应用程序是否可以通过的关键问题不是“有多少用户?”甚至“多少个流程?”,但“我的交易要花多长时间?”

如果您的所有交易时间都不到一秒,那也许还好,如果有些交易需要几个小时才能完成,可能还不行,因为所有其他待处理的交易都将等待它们完成。是否满足条件的决定将取决于您自己的性能要求,即,我的用户使用事务访问数据库要等待多长时间。

--EDIT

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

#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证明了线程引入了解决的许多问题。 (...)


所以,再说一遍...我绝对不知道上述优点。太短了,无法发表评论。

#6 楼

仅当您有多个并行查询进入数据库时​​,多线程数据库才会对您有利。这取决于您拥有的用户数。如果您同时有十个以上的用户在处理该应用程序,则很可能他们将同时在数据库上产生多个查询。

此外,仅当CPU上有多核时,多线程数据库才能受益。如果有单核,则多线程数据库必须将作业排队,并在单核上顺序执行它们。如果有多核,则每个核可以并行运行一个线程。从而获得更好的性能。

这可以回答您的查询吗?

评论


即使在单核系统上,多线程数据库也很有用。它可以防止一个长时间运行的查询阻止所有其他数据库访问,另外,您可能让多个线程在磁盘或网络I / O上等待,而另一个线程正在主动解析查询,处理预取的数据等。

–匿名
2011年5月24日17:02

一个用户可能正在使用一个使某些操作并行化的程序。如果数据库也具有多线程/多处理功能,则该程序最有可能受益。

– joanolo
16 Dec 25'1:22