精华内容
下载资源
问答
  • 如何设置数据库连接池大小

    千次阅读 2019-06-05 15:25:21
    目录 一、笔者前言 二、正菜开始 三、假设你的服务1万...基本上来说,部分项目需要跟数据库做交互,那么,数据库连接池的大小设置成多合适呢? 一些开发老鸟可能还会告诉你:没关系,尽量设置的些,...

    目录

     

    一、笔者前言

    二、正菜开始

    三、假设你的服务有1万并发的访问

    四、为啥有这种效果?

    五、其他应该考虑到的因素

    六、连接数计算公式

    七、结论:你需要的是一个小连接池,和一个等待连接的线程队列

    八、额外需要注意的点

    一、笔者前言

    基本上来说,大部分项目都需要跟数据库做交互,那么,数据库连接池的大小设置成多大合适呢?

    一些开发老鸟可能还会告诉你:没关系,尽量设置的大些,比如设置成 200,这样数据库性能会高些,吞吐量也会大些!

    你也许会点头称是,真的是这样吗?看完这篇文章,也许会颠覆你的认知哦!

     

    二、正菜开始

    可以很直接的说,关于数据库连接池大小的设置,每个开发者都可能在一环节掉进坑里,事实上呢,大部分程序员可能都会依靠自己的直觉去设置它的大小,设置成 100 ?思量许久后,自顾自想,应该差不多吧?

     

    三、假设你的服务有1万并发的访问

    不妨意淫一下,你手里有个网站,并发压力虽然还没到 Facebook 那个级别,但是呢?也有个1万上下的并发量!也就是说差不多2万左右的 TPS。

    那么问题来了!这个网站的数据库连接池应该设置成多大合适呢?

    其实这个问法本身就是有问题的,我们需要反过来问,正确问法应该是:

    “这个网站的数据库连接池应该设置成多小合适呢?”

     

    PS: 这里有一个 Oracle 性能小组发布的简短视频,链接地址为 

    http://www.dailymotion.com/video/x2s8uec,友情提示,需要科学上网才能访问哦!

     

    口述一下,视频中对 Oracle 数据库进行了压力测试,模拟 9600 个并发线程来操作数据库,每两次数据库操作之间 sleep 550ms,注意,视频中刚开始设置的线程池大小为 2048。

    让我们来看看数据库连接池的大小为 2048 性能测试结果的鬼样子:

    每个请求要在连接池队列里等待 33ms,获得连接之后,执行SQL需要耗时77ms, CPU 消耗维持在 95% 左右;

    接下来,我们将连接池的大小改小点,设置成 1024,其他测试参数不变,结果咋样?

    "这里,获取连接等待时长基本不变,但是 SQL 的执行耗时降低了!"

    哎呦,有长进哦!

    接下来,我们再设置小些,连接池的大小降低到 96,并发数等其他参数不变,看看结果如何:

    每个请求在连接池队列中的平均等待时间为 1ms, SQL 执行耗时为 2ms.

    我去!什么鬼?

    我们没调整任何东西,仅仅只是将数据库连接池的大小降低了,这样,就能把之前平均 100ms 响应时间缩短到了 3ms。吞吐量指数级上升啊!

    你这也太溜了!

     

    四、为啥有这种效果?

    我们不妨想一下,为啥 Nginx 内部仅仅使用了 4 个线程,其性能就大大超越了 100 个进程的 Apache HTTPD 呢?追究其原因的话,回想一下计算机科学的基础知识,答案其实非常明显。

    要知道,即使是单核 CPU 的计算机也能“同时”运行着数百个线程。但我们其实都知道,这只不过是操作系统快速切换时间片,跟我们玩的一个小把戏罢了。

    一核 CPU同一时刻只能执行一个线程,然后操作系统切换上下文,CPU 核心快速调度,执行另一个线程的代码,不停反复,给我们造成了所有进程同时运行假象。

    其实,在一核 CPU 的机器上,顺序执行A和B永远比通过时间分片切换“同时”执行A和B要快,其中原因,学过操作系统这门课程的童鞋应该很清楚。一旦线程的数量超过了 CPU 核心的数量,再增加线程数系统就只会更慢,而不是更快,因为这里涉及到上下文切换耗费的额外的性能。

    说到这里,你应该恍然大悟了 ……

     

    五、其他应该考虑到的因素

    上小节中说到了主要原因,但其实没有这么简单,我们还需要考虑到一些其他的因素。

    当我们在寻找数据库的性能瓶颈时,大致可归为三类:

    CPU

    磁盘 IO

    网络 IO

    也许你会说,还有内存这一因素?内存的确是需要考虑的,但是比起磁盘IO和网络IO,稍显微不足道,这里就不加了。

    假设我们不考虑磁盘 IO 和网络 IO,就很好定论了,在一个 8 核的服务器上,数据库连接数/线程数设置为 8 能够提供最优的性能,如果再增加连接数,反而会因为上下文切换导致性能下降。

    大家都知道,数据库通常把数据存储在磁盘上,而磁盘呢,通常是由一些旋转着的金属碟片和一个装在步进马达上的读写头组成的。读/写头同一时刻只能出现在一个位置,当它需要再次执行读写操作时,它必须“寻址”到另外一个位置才能完成任务。所以呢?这里就有了寻址的耗时,此外还有旋转耗时,读写头需要等待磁盘碟片上的目标数据“旋转到位”才能进行读写操作。使用缓存当然是能够提升性能的,但上述原理仍然适用。

    在这段("I/O等待")时间内,线程是处于“阻塞”等待状态,也就是说没干啥正事!此时操作系统可以将这个空闲的CPU 核心用于服务其他线程。

    这里我们可以总结一下,当你的线程处理的是 I/O 密集型业务时,便可以让线程/连接数设置的比 CPU核心大一些,这样就能够在同样的时间内,完成更多的工作,提升吞吐量。

    那么问题又来了?

    大小设置成多少合适呢?

    这要取决于磁盘,如果你使用的是 SSD 固态硬盘,它不需要寻址,也不需要旋转碟片。打住打住!!!你千万可别理所当然的认为:“既然SSD速度更快,我们把线程数的大小设置的大些吧!!”

    结论正好相反!无需寻址和没有旋回耗时的确意味着更少的阻塞,所以更少的线程(更接近于CPU核心数)会发挥出更高的性能。只有当阻塞密集时,更多的线程数才能发挥出更好的性能。

    上面我们已经说过了磁盘 IO, 接下来我们谈谈网络 IO!

    网络 IO 其实也是非常相似的。通过以太网接口读写数据时也会造成阻塞,10G带宽会比1G带宽的阻塞耗时少一些,而 1G 带宽又会比 100M 带宽的阻塞少一些。通常情况下,我们把网络 IO 放在第三顺位来考虑,然而有些人会在性能计算中忽略网络 IO 带来的影响。

    上图是 PostgreSQL 的基准性能测试数据,从图中我们可以看到,TPS 在连接数达到 50 时开始变缓。回过头来想下,在上面 Oracle 的性能测试视频中,测试人员们将连接数从 2048 降到了 96,实际上 96 还是太高了,除非你的服务器 CPU 核心数有 16 或 32。

     

    六、连接数计算公式

    下面公式由 PostgreSQL 提供,不过底层原理是不变的,它适用于市面上绝大部分数据库产品。还有,你应该模拟预期的访问量,并通过下面的公式先设置一个偏合理的值,然后在实际的测试中,通过微调,来寻找最合适的连接数大小。

    连接数 = ((核心数 * 2) + 有效磁盘数)

    核心数不应包含超线程(hyper thread),即使打开了超线程也是如此,如果热点数据全被缓存了,那么有效磁盘数实际是0,随着缓存命中率的下降,有效磁盘数也逐渐趋近于实际的磁盘数。另外需要注意,这一公式作用于SSD 的效果如何,尚未明了。

    好了,按照这个公式,如果说你的服务器 CPU 是 4核 i7 的,连接池大小应该为 ((4*2)+1)=9。

    取个整, 我们就设置为 10 吧。你这个行不行啊?10 也太小了吧!

    你要是觉得不太行的话,可以跑个性能测试看看,我们可以保证,它能轻松支撑 3000 用户以 6000 TPS 的速率并发执行简单查询的场景。你还可以将连接池大小超过 10,那时,你会看到响应时长开始增加,TPS 开始下降。

     

    七、结论:你需要的是一个小连接池,和一个等待连接的线程队列

    假设说你有 10000 个并发访问,而你设置了连接池大小为 10000,你怕是石乐志哦。

    改成 1000,太高?改成 100?还是太多了。

    你仅仅需要一个大小为 10 数据库连接池,然后让剩下的业务线程都在队列里等待就可以了。

    连接池中的连接数量大小应该设置成:数据库能够有效同时进行的查询任务数(通常情况下来说不会高于 2*CPU核心数)。

    你应该经常会看到一些用户量不是很大的 web 应用中,为应付大约十来个的并发,却将数据库连接池设置成 100, 200 的情况。请不要过度配置您的数据库连接池的大小。

     

    八、额外需要注意的点

     

    实际上,连接池的大小的设置还是要结合实际的业务场景来说事。

    比如说,你的系统同时混合了长事务和短事务,这时,根据上面的公司来计算就很难办了。正确的做法应该是创建两个连接池,一个服务于长事务,一个服务于"实时"查询,也就是短事务。

    还有一种情况,比方说一个系统执行一个任务队列,业务上要求同一时间内只允许执行一定数量的任务,这时,我们就应该让并发任务数去适配连接池连接数,而不是连接数大小去适配并发任务数。



    作者:大鱼炖海棠
    链接:https://www.jianshu.com/p/3895926e6c37
    来源:简书
    简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

    展开全文
  • 目录 一、前言 二、正菜开始 ...基本上来说,部分项目需要跟数据库做交互,那么,数据库连接池的大小设置成多合适呢? 一些开发老鸟可能还会告诉你:没关系,尽量设置的些,比如设置成 2...

    目录

    一、前言

    二、正菜开始

    三、假设你的服务有1万并发的访问

    四、为啥有这种效果?

    五、其他应该考虑到的因素

    六、连接数计算公式

    七、结论:你需要的是一个小连接池,和一个等待连接的线程队列

    八、额外需要注意的点


    一、前言

    基本上来说,大部分项目都需要跟数据库做交互,那么,数据库连接池的大小设置成多大合适呢?

    一些开发老鸟可能还会告诉你:没关系,尽量设置的大些,比如设置成 200,这样数据库性能会高些,吞吐量也会大些!

    你也许会点头称是,真的是这样吗?看完这篇文章,也许会颠覆你的认知哦!

    二、正菜开始

    可以很直接的说,关于数据库连接池大小的设置,每个开发者都可能在一环节掉进坑里,事实上呢,大部分程序员可能都会依靠自己的直觉去设置它的大小,设置成 100 ?思量许久后,自顾自想,应该差不多吧?

    三、假设你的服务有1万并发的访问

    不妨意淫一下,你手里有个网站,并发压力虽然还没到 Facebook 那个级别,但是呢?也有个1万上下的并发量!也就是说差不多2万左右的 TPS。

    那么问题来了!这个网站的数据库连接池应该设置成多大合适呢?

    其实这个问法本身就是有问题的,我们需要反过来问,正确问法应该是:

    “这个网站的数据库连接池应该设置成多小合适呢?”

    PS: 这里有一个 Oracle 性能小组发布的简短视频,链接地址为 http://www.dailymotion.com/video/x2s8uec,友情提示,需要XX上网哦!

    口述一下,视频中对 Oracle 数据库进行了压力测试,模拟 9600 个并发线程来操作数据库,每两次数据库操作之间 sleep 550ms,注意,视频中刚开始设置的线程池大小为 2048。

    让我们来看看数据库连接池的大小为 2048 性能测试结果的鬼样子:

    每个请求要在连接池队列里等待 33ms,获得连接之后,执行SQL需要耗时77ms, CPU 消耗维持在 95% 左右;

    接下来,我们将连接池的大小改小点,设置成 1024,其他测试参数不变,结果咋样?

    "这里,获取连接等待时长基本不变,但是 SQL 的执行耗时降低了!"

    哎呦,有长进哦!

    接下来,我们再设置小些,连接池的大小降低到 96,并发数等其他参数不变,看看结果如何:

    每个请求在连接池队列中的平均等待时间为 1ms, SQL 执行耗时为 2ms.

    我去!什么鬼?

    我们没调整任何东西,仅仅只是将数据库连接池的大小降低了,这样,就能把之前平均 100ms 响应时间缩短到了 3ms。吞吐量指数级上升啊!

    你这也太溜了!

    四、为啥有这种效果?

    我们不妨想一下,为啥 Nginx 内部仅仅使用了 4 个线程,其性能就大大超越了 100 个进程的 Apache HTTPD 呢?追究其原因的话,回想一下计算机科学的基础知识,答案其实非常明显。

    要知道,即使是单核 CPU 的计算机也能“同时”运行着数百个线程。但我们其实都知道,这只不过是操作系统快速切换时间片,跟我们玩的一个小把戏罢了。

    一核 CPU同一时刻只能执行一个线程,然后操作系统切换上下文,CPU 核心快速调度,执行另一个线程的代码,不停反复,给我们造成了所有进程同时运行假象。

    其实,在一核 CPU 的机器上,顺序执行AB永远比通过时间分片切换“同时”执行AB要快,其中原因,学过操作系统这门课程的童鞋应该很清楚。一旦线程的数量超过了 CPU 核心的数量,再增加线程数系统就只会更慢,而不是更快,因为这里涉及到上下文切换耗费的额外的性能。

    说到这里,你应该恍然大悟了 ……

    五、其他应该考虑到的因素

    上小节中说到了主要原因,但其实没有这么简单,我们还需要考虑到一些其他的因素。

    当我们在寻找数据库的性能瓶颈时,大致可归为三类:

    • CPU

    • 磁盘 IO

    • 网络 IO

    也许你会说,还有内存这一因素?内存的确是需要考虑的,但是比起磁盘IO网络IO,稍显微不足道,这里就不加了。

    假设我们不考虑磁盘 IO 和网络 IO,就很好定论了,在一个 8 核的服务器上,数据库连接数/线程数设置为 8 能够提供最优的性能,如果再增加连接数,反而会因为上下文切换导致性能下降。

    大家都知道,数据库通常把数据存储在磁盘上,而磁盘呢,通常是由一些旋转着的金属碟片和一个装在步进马达上的读写头组成的。读/写头同一时刻只能出现在一个位置,当它需要再次执行读写操作时,它必须“寻址”到另外一个位置才能完成任务。所以呢?这里就有了寻址的耗时,此外还有旋转耗时,读写头需要等待磁盘碟片上的目标数据“旋转到位”才能进行读写操作。使用缓存当然是能够提升性能的,但上述原理仍然适用。

    在这段("I/O等待")时间内,线程是处于“阻塞”等待状态,也就是说没干啥正事!此时操作系统可以将这个空闲的CPU 核心用于服务其他线程。

    这里我们可以总结一下,当你的线程处理的是 I/O 密集型业务时,便可以让线程/连接数设置的比 CPU核心大一些,这样就能够在同样的时间内,完成更多的工作,提升吞吐量。

    那么问题又来了?

    大小设置成多少合适呢?

    这要取决于磁盘,如果你使用的是 SSD 固态硬盘,它不需要寻址,也不需要旋转碟片。打住打住!!!你千万可别理所当然的认为:“既然SSD速度更快,我们把线程数的大小设置的大些吧!!

    结论正好相反!无需寻址和没有旋回耗时的确意味着更少的阻塞,所以更少的线程(更接近于CPU核心数)会发挥出更高的性能。只有当阻塞密集时,更多的线程数才能发挥出更好的性能。

    上面我们已经说过了磁盘 IO, 接下来我们谈谈网络 IO!

    网络 IO 其实也是非常相似的。通过以太网接口读写数据时也会造成阻塞,10G带宽会比1G带宽的阻塞耗时少一些,而 1G 带宽又会比 100M 带宽的阻塞少一些。通常情况下,我们把网络 IO 放在第三顺位来考虑,然而有些人会在性能计算中忽略网络 IO 带来的影响。

    上图是 PostgreSQL 的基准性能测试数据,从图中我们可以看到,TPS 在连接数达到 50 时开始变缓。回过头来想下,在上面 Oracle 的性能测试视频中,测试人员们将连接数从 2048 降到了 96,实际上 96 还是太高了,除非你的服务器 CPU 核心数有 16 或 32。

    六、连接数计算公式

    下面公式由 PostgreSQL 提供,不过底层原理是不变的,它适用于市面上绝大部分数据库产品。还有,你应该模拟预期的访问量,并通过下面的公式先设置一个偏合理的值,然后在实际的测试中,通过微调,来寻找最合适的连接数大小。

    连接数 = ((核心数 * 2) + 有效磁盘数)

    核心数不应包含超线程(hyper thread),即使打开了超线程也是如此,如果热点数据全被缓存了,那么有效磁盘数实际是0,随着缓存命中率的下降,有效磁盘数也逐渐趋近于实际的磁盘数。另外需要注意,这一公式作用于SSD 的效果如何,尚未明了。

    好了,按照这个公式,如果说你的服务器 CPU 是 4核 i7 的,连接池大小应该为 ((4*2)+1)=9

    取个整, 我们就设置为 10 吧。你这个行不行啊?10 也太小了吧!

    你要是觉得不太行的话,可以跑个性能测试看看,我们可以保证,它能轻松支撑 3000 用户以 6000 TPS 的速率并发执行简单查询的场景。你还可以将连接池大小超过 10,那时,你会看到响应时长开始增加,TPS 开始下降。

    七、结论:你需要的是一个小连接池,和一个等待连接的线程队列

    假设说你有 10000 个并发访问,而你设置了连接池大小为 10000,你怕是石乐志哦。

    改成 1000,太高?改成 100?还是太多了。

    你仅仅需要一个大小为 10 数据库连接池,然后让剩下的业务线程都在队列里等待就可以了。

    连接池中的连接数量大小应该设置成:数据库能够有效同时进行的查询任务数(通常情况下来说不会高于 2*CPU核心数)。

    你应该经常会看到一些用户量不是很大的 web 应用中,为应付大约十来个的并发,却将数据库连接池设置成 100, 200 的情况。请不要过度配置您的数据库连接池的大小。

    八、额外需要注意的点

    实际上,连接池的大小的设置还是要结合实际的业务场景来说事。

    比如说,你的系统同时混合了长事务短事务,这时,根据上面的公式来计算就很难办了。正确的做法应该是创建两个连接池,一个服务于长事务,一个服务于"实时"查询,也就是短事务。

    还有一种情况,比方说一个系统执行一个任务队列,业务上要求同一时间内只允许执行一定数量的任务,这时,我们就应该让并发任务数去适配连接池连接数,而不是连接数大小去适配并发任务数。

    原文链接:

    https://mp.weixin.qq.com/s/Esop6mmjYt0mw_DCo9QbOw

    https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing

    展开全文
  • 目录 一、笔者前言 二、正菜开始 三、假设你的服务1万并发的访问 ... 四、为啥有这种效果?...基本上来说,部分项目需要跟数据库做交互,那么,数据库连接池的大小设置成多合适呢? ...

    目录

    • 一、笔者前言

    • 二、正菜开始

    • 三、假设你的服务有1万并发的访问

    • 四、为啥有这种效果?

    • 五、其他应该考虑到的因素

    • 六、连接数计算公式

    • 七、结论:你需要的是一个小连接池,和一个等待连接的线程队列

    • 八、额外需要注意的点

    一、前言

    基本上来说,大部分项目都需要跟数据库做交互,那么,数据库连接池的大小设置成多大合适呢?

    一些开发老鸟可能还会告诉你:没关系,尽量设置的大些,比如设置成 200,这样数据库性能会高些,吞吐量也会大些!

    你也许会点头称是,真的是这样吗?看完这篇文章,也许会颠覆你的认知哦!

    二、正菜开始

    可以很直接的说,关于数据库连接池大小的设置,每个开发者都可能在一环节掉进坑里,事实上呢,大部分程序员可能都会依靠自己的直觉去设置它的大小,设置成 100 ?思量许久后,自顾自想,应该差不多吧?

    三、假设你的服务有1万并发的访问

    不妨意淫一下,你手里有个网站,并发压力虽然还没到 Facebook 那个级别,但是呢?也有个1万上下的并发量!也就是说差不多2万左右的 TPS。

    那么问题来了!这个网站的数据库连接池应该设置成多大合适呢?

    其实这个问法本身就是有问题的,我们需要反过来问,正确问法应该是:

    “这个网站的数据库连接池应该设置成多小合适呢?”

    PS: 这里有一个 Oracle 性能小组发布的简短视频,链接地址为 http://www.dailymotion.com/video/x2s8uec,友情提示,需要科学上网才能访问哦!

    口述一下,视频中对 Oracle 数据库进行了压力测试,模拟 9600 个并发线程来操作数据库,每两次数据库操作之间 sleep 550ms,注意,视频中刚开始设置的线程池大小为 2048。

    让我们来看看数据库连接池的大小为 2048 性能测试结果的鬼样子:

    每个请求要在连接池队列里等待 33ms,获得连接之后,执行SQL需要耗时77ms, CPU 消耗维持在 95% 左右;

    接下来,我们将连接池的大小改小点,设置成 1024,其他测试参数不变,结果咋样?

    "这里,获取连接等待时长基本不变,但是 SQL 的执行耗时降低了!"

    哎呦,有长进哦!

    接下来,我们再设置小些,连接池的大小降低到 96,并发数等其他参数不变,看看结果如何:

    每个请求在连接池队列中的平均等待时间为 1ms, SQL 执行耗时为 2ms.

    我去!什么鬼?

    我们没调整任何东西,仅仅只是将数据库连接池的大小降低了,这样,就能把之前平均 100ms 响应时间缩短到了 3ms。吞吐量指数级上升啊!

    你这也太溜了!

    四、为啥有这种效果?

    我们不妨想一下,为啥 Nginx 内部仅仅使用了 4 个线程,其性能就大大超越了 100 个进程的 Apache HTTPD 呢?追究其原因的话,回想一下计算机科学的基础知识,答案其实非常明显。

    要知道,即使是单核 CPU 的计算机也能“同时”运行着数百个线程。但我们其实都知道,这只不过是操作系统快速切换时间片,跟我们玩的一个小把戏罢了。

    一核 CPU同一时刻只能执行一个线程,然后操作系统切换上下文,CPU 核心快速调度,执行另一个线程的代码,不停反复,给我们造成了所有进程同时运行假象。

    其实,在一核 CPU 的机器上,顺序执行AB永远比通过时间分片切换“同时”执行AB要快,其中原因,学过操作系统这门课程的童鞋应该很清楚。一旦线程的数量超过了 CPU 核心的数量,再增加线程数系统就只会更慢,而不是更快,因为这里涉及到上下文切换耗费的额外的性能。

    说到这里,你应该恍然大悟了 ……

    五、其他应该考虑到的因素

    上小节中说到了主要原因,但其实没有这么简单,我们还需要考虑到一些其他的因素。

    当我们在寻找数据库的性能瓶颈时,大致可归为三类:

    • CPU

    • 磁盘 IO

    • 网络 IO

    也许你会说,还有内存这一因素?内存的确是需要考虑的,但是比起磁盘IO网络IO,稍显微不足道,这里就不加了。

    假设我们不考虑磁盘 IO 和网络 IO,就很好定论了,在一个 8 核的服务器上,数据库连接数/线程数设置为 8 能够提供最优的性能,如果再增加连接数,反而会因为上下文切换导致性能下降。

    大家都知道,数据库通常把数据存储在磁盘上,而磁盘呢,通常是由一些旋转着的金属碟片和一个装在步进马达上的读写头组成的。读/写头同一时刻只能出现在一个位置,当它需要再次执行读写操作时,它必须“寻址”到另外一个位置才能完成任务。所以呢?这里就有了寻址的耗时,此外还有旋转耗时,读写头需要等待磁盘碟片上的目标数据“旋转到位”才能进行读写操作。使用缓存当然是能够提升性能的,但上述原理仍然适用。

    在这段("I/O等待")时间内,线程是处于“阻塞”等待状态,也就是说没干啥正事!此时操作系统可以将这个空闲的CPU 核心用于服务其他线程。

    这里我们可以总结一下,当你的线程处理的是 I/O 密集型业务时,便可以让线程/连接数设置的比 CPU核心大一些,这样就能够在同样的时间内,完成更多的工作,提升吞吐量。

    那么问题又来了?

    大小设置成多少合适呢?

    这要取决于磁盘,如果你使用的是 SSD 固态硬盘,它不需要寻址,也不需要旋转碟片。打住打住!!!你千万可别理所当然的认为:“既然SSD速度更快,我们把线程数的大小设置的大些吧!!

    结论正好相反!无需寻址和没有旋回耗时的确意味着更少的阻塞,所以更少的线程(更接近于CPU核心数)会发挥出更高的性能。只有当阻塞密集时,更多的线程数才能发挥出更好的性能。

    上面我们已经说过了磁盘 IO, 接下来我们谈谈网络 IO!

    网络 IO 其实也是非常相似的。通过以太网接口读写数据时也会造成阻塞,10G带宽会比1G带宽的阻塞耗时少一些,而 1G 带宽又会比 100M 带宽的阻塞少一些。通常情况下,我们把网络 IO 放在第三顺位来考虑,然而有些人会在性能计算中忽略网络 IO 带来的影响。

    上图是 PostgreSQL 的基准性能测试数据,从图中我们可以看到,TPS 在连接数达到 50 时开始变缓。回过头来想下,在上面 Oracle 的性能测试视频中,测试人员们将连接数从 2048 降到了 96,实际上 96 还是太高了,除非你的服务器 CPU 核心数有 16 或 32。

    六、连接数计算公式

    下面公式由 PostgreSQL 提供,不过底层原理是不变的,它适用于市面上绝大部分数据库产品。还有,你应该模拟预期的访问量,并通过下面的公式先设置一个偏合理的值,然后在实际的测试中,通过微调,来寻找最合适的连接数大小。

    连接数 = ((核心数 * 2) + 有效磁盘数)

    核心数不应包含超线程(hyper thread),即使打开了超线程也是如此,如果热点数据全被缓存了,那么有效磁盘数实际是0,随着缓存命中率的下降,有效磁盘数也逐渐趋近于实际的磁盘数。另外需要注意,这一公式作用于SSD 的效果如何,尚未明了。

    好了,按照这个公式,如果说你的服务器 CPU 是 4核 i7 的,连接池大小应该为 ((4*2)+1)=9

    取个整, 我们就设置为 10 吧。你这个行不行啊?10 也太小了吧!

    你要是觉得不太行的话,可以跑个性能测试看看,我们可以保证,它能轻松支撑 3000 用户以 6000 TPS 的速率并发执行简单查询的场景。你还可以将连接池大小超过 10,那时,你会看到响应时长开始增加,TPS 开始下降。

    七、你需要的是一个小连接池,和一个等待连接的线程队列

    假设说你有 10000 个并发访问,而你设置了连接池大小为 10000,你怕是石乐志哦。

    改成 1000,太高?改成 100?还是太多了。

    你仅仅需要一个大小为 10 数据库连接池,然后让剩下的业务线程都在队列里等待就可以了。

    连接池中的连接数量大小应该设置成:数据库能够有效同时进行的查询任务数(通常情况下来说不会高于 2*CPU核心数)。

    你应该经常会看到一些用户量不是很大的 web 应用中,为应付大约十来个的并发,却将数据库连接池设置成 100, 200 的情况。请不要过度配置您的数据库连接池的大小。

    八、额外需要注意的点

    实际上,连接池的大小的设置还是要结合实际的业务场景来说事。

    比如说,你的系统同时混合了长事务短事务,这时,根据上面的公式来计算就很难办了。正确的做法应该是创建两个连接池,一个服务于长事务,一个服务于"实时"查询,也就是短事务。

    还有一种情况,比方说一个系统执行一个任务队列,业务上要求同一时间内只允许执行一定数量的任务,这时,我们就应该让并发任务数去适配连接池连接数,而不是连接数大小去适配并发任务数。

    参考链接

    【1】https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing

    展开全文
  • 目录 一、笔者前言 二、正菜开始 三、假设你的服务1万并发的访问 ... 四、为啥有这种效果?...基本上来说,部分项目需要跟数据库做交互,那么,数据库连接池的大小设置成多合适呢? ...

    目录

    • 一、笔者前言

    • 二、正菜开始

    • 三、假设你的服务有1万并发的访问

    • 四、为啥有这种效果?

    • 五、其他应该考虑到的因素

    • 六、连接数计算公式

    • 七、结论:你需要的是一个小连接池,和一个等待连接的线程队列

    • 八、额外需要注意的点

    一、前言

    基本上来说,大部分项目都需要跟数据库做交互,那么,数据库连接池的大小设置成多大合适呢?

    一些开发老鸟可能还会告诉你:没关系,尽量设置的大些,比如设置成 200,这样数据库性能会高些,吞吐量也会大些!

    你也许会点头称是,真的是这样吗?看完这篇文章,也许会颠覆你的认知哦!

     

    二、正菜开始

    可以很直接的说,关于数据库连接池大小的设置,每个开发者都可能在一环节掉进坑里,事实上呢,大部分程序员可能都会依靠自己的直觉去设置它的大小,设置成 100 ?思量许久后,自顾自想,应该差不多吧?

    三、假设你的服务有1万并发的访问

    不妨意淫一下,你手里有个网站,并发压力虽然还没到 Facebook 那个级别,但是呢?也有个1万上下的并发量!也就是说差不多2万左右的 TPS。

    那么问题来了!这个网站的数据库连接池应该设置成多大合适呢?

    其实这个问法本身就是有问题的,我们需要反过来问,正确问法应该是:

    “这个网站的数据库连接池应该设置成多小合适呢?”

    PS: 这里有一个 Oracle 性能小组发布的简短视频,链接地址为 http://www.dailymotion.com/video/x2s8uec,友情提示,需要科学上网才能访问哦!

     

    口述一下,视频中对 Oracle 数据库进行了压力测试,模拟 9600 个并发线程来操作数据库,每两次数据库操作之间 sleep 550ms,注意,视频中刚开始设置的线程池大小为 2048。

    让我们来看看数据库连接池的大小为 2048 性能测试结果的鬼样子:

    每个请求要在连接池队列里等待 33ms,获得连接之后,执行SQL需要耗时77ms, CPU 消耗维持在 95% 左右;

    接下来,我们将连接池的大小改小点,设置成 1024,其他测试参数不变,结果咋样?

    "这里,获取连接等待时长基本不变,但是 SQL 的执行耗时降低了!"

    哎呦,有长进哦!

    接下来,我们再设置小些,连接池的大小降低到 96,并发数等其他参数不变,看看结果如何:

    每个请求在连接池队列中的平均等待时间为 1ms, SQL 执行耗时为 2ms.

    我去!什么鬼?

    我们没调整任何东西,仅仅只是将数据库连接池的大小降低了,这样,就能把之前平均 100ms 响应时间缩短到了 3ms。吞吐量指数级上升啊!

    你这也太溜了!

     

    四、为啥有这种效果?

    我们不妨想一下,为啥 Nginx 内部仅仅使用了 4 个线程,其性能就大大超越了 100 个进程的 Apache HTTPD 呢?追究其原因的话,回想一下计算机科学的基础知识,答案其实非常明显。

    要知道,即使是单核 CPU 的计算机也能“同时”运行着数百个线程。但我们其实都知道,这只不过是操作系统快速切换时间片,跟我们玩的一个小把戏罢了。

    一核 CPU同一时刻只能执行一个线程,然后操作系统切换上下文,CPU 核心快速调度,执行另一个线程的代码,不停反复,给我们造成了所有进程同时运行假象。

    其实,在一核 CPU 的机器上,顺序执行AB永远比通过时间分片切换“同时”执行AB要快,其中原因,学过操作系统这门课程的童鞋应该很清楚。一旦线程的数量超过了 CPU 核心的数量,再增加线程数系统就只会更慢,而不是更快,因为这里涉及到上下文切换耗费的额外的性能。

    说到这里,你应该恍然大悟了 ……

     

    五、其他应该考虑到的因素

    上小节中说到了主要原因,但其实没有这么简单,我们还需要考虑到一些其他的因素。

    当我们在寻找数据库的性能瓶颈时,大致可归为三类:

    • CPU

    • 磁盘 IO

    • 网络 IO

    也许你会说,还有内存这一因素?内存的确是需要考虑的,但是比起磁盘IO网络IO,稍显微不足道,这里就不加了。

    假设我们不考虑磁盘 IO 和网络 IO,就很好定论了,在一个 8 核的服务器上,数据库连接数/线程数设置为 8 能够提供最优的性能,如果再增加连接数,反而会因为上下文切换导致性能下降。

    大家都知道,数据库通常把数据存储在磁盘上,而磁盘呢,通常是由一些旋转着的金属碟片和一个装在步进马达上的读写头组成的。读/写头同一时刻只能出现在一个位置,当它需要再次执行读写操作时,它必须“寻址”到另外一个位置才能完成任务。所以呢?这里就有了寻址的耗时,此外还有旋转耗时,读写头需要等待磁盘碟片上的目标数据“旋转到位”才能进行读写操作。使用缓存当然是能够提升性能的,但上述原理仍然适用。

    在这段("I/O等待")时间内,线程是处于“阻塞”等待状态,也就是说没干啥正事!此时操作系统可以将这个空闲的CPU 核心用于服务其他线程。

    这里我们可以总结一下,当你的线程处理的是 I/O 密集型业务时,便可以让线程/连接数设置的比 CPU核心大一些,这样就能够在同样的时间内,完成更多的工作,提升吞吐量。

    那么问题又来了?

    大小设置成多少合适呢?

    这要取决于磁盘,如果你使用的是 SSD 固态硬盘,它不需要寻址,也不需要旋转碟片。打住打住!!!你千万可别理所当然的认为:“既然SSD速度更快,我们把线程数的大小设置的大些吧!!

    结论正好相反!无需寻址和没有旋回耗时的确意味着更少的阻塞,所以更少的线程(更接近于CPU核心数)会发挥出更高的性能。只有当阻塞密集时,更多的线程数才能发挥出更好的性能。

    上面我们已经说过了磁盘 IO, 接下来我们谈谈网络 IO!

    网络 IO 其实也是非常相似的。通过以太网接口读写数据时也会造成阻塞,10G带宽会比1G带宽的阻塞耗时少一些,而 1G 带宽又会比 100M 带宽的阻塞少一些。通常情况下,我们把网络 IO 放在第三顺位来考虑,然而有些人会在性能计算中忽略网络 IO 带来的影响。

     

    上图是 PostgreSQL 的基准性能测试数据,从图中我们可以看到,TPS 在连接数达到 50 时开始变缓。回过头来想下,在上面 Oracle 的性能测试视频中,测试人员们将连接数从 2048 降到了 96,实际上 96 还是太高了,除非你的服务器 CPU 核心数有 16 或 32。

    六、连接数计算公式

    下面公式由 PostgreSQL 提供,不过底层原理是不变的,它适用于市面上绝大部分数据库产品。还有,你应该模拟预期的访问量,并通过下面的公式先设置一个偏合理的值,然后在实际的测试中,通过微调,来寻找最合适的连接数大小。

    连接数 = ((核心数 * 2) + 有效磁盘数)

    核心数不应包含超线程(hyper thread),即使打开了超线程也是如此,如果热点数据全被缓存了,那么有效磁盘数实际是0,随着缓存命中率的下降,有效磁盘数也逐渐趋近于实际的磁盘数。另外需要注意,这一公式作用于SSD 的效果如何,尚未明了。

    好了,按照这个公式,如果说你的服务器 CPU 是 4核 i7 的,连接池大小应该为 ((4*2)+1)=9

    取个整, 我们就设置为 10 吧。你这个行不行啊?10 也太小了吧!

     

    你要是觉得不太行的话,可以跑个性能测试看看,我们可以保证,它能轻松支撑 3000 用户以 6000 TPS 的速率并发执行简单查询的场景。你还可以将连接池大小超过 10,那时,你会看到响应时长开始增加,TPS 开始下降。

    七、结论:你需要的是一个小连接池,和一个等待连接的线程队列

    假设说你有 10000 个并发访问,而你设置了连接池大小为 10000,你怕是石乐志哦。

    改成 1000,太高?改成 100?还是太多了。

    你仅仅需要一个大小为 10 数据库连接池,然后让剩下的业务线程都在队列里等待就可以了。

    连接池中的连接数量大小应该设置成:数据库能够有效同时进行的查询任务数(通常情况下来说不会高于 2*CPU核心数)。

    你应该经常会看到一些用户量不是很大的 web 应用中,为应付大约十来个的并发,却将数据库连接池设置成 100, 200 的情况。请不要过度配置您的数据库连接池的大小。

    八、额外需要注意的点

    实际上,连接池的大小的设置还是要结合实际的业务场景来说事。

    比如说,你的系统同时混合了长事务短事务,这时,根据上面的公式来计算就很难办了。正确的做法应该是创建两个连接池,一个服务于长事务,一个服务于"实时"查询,也就是短事务。

    还有一种情况,比方说一个系统执行一个任务队列,业务上要求同一时间内只允许执行一定数量的任务,这时,我们就应该让并发任务数去适配连接池连接数,而不是连接数大小去适配并发任务数。

    展开全文
  • 目录 一、笔者前言 二、正菜开始 三、假设你的服务1万并发的访问 ... 四、为啥有这种效果?...基本上来说,部分项目需要跟数据库做交互,那么,数据库连接池的大小设置成多合适呢? ...
  • 、其他应该考虑到的因素六、连接数计算公式七、结论:你需要的是一个小连接池,和一个等待连接的线程队列八、额外需要注意的点一、前言基本上来说,部分项目需要跟数据库做交互,那么,数据库连接池的大小设置...
  • 目录 一、笔者前言 二、正菜开始 ...基本上来说,部分项目需要跟数据库做交互,那么,数据库连接池的大小设置成多合适呢? 一些开发老鸟可能还会告诉你:没关系,尽量设置的些,比如设置成 20...
  • 基本上来说,部分项目需要跟数据库做交互,那么,数据库连接池的大小设置成多合适呢? 一些开发老鸟可能还会告诉你:没关系,尽量设置的些,比如设置成 200,这样数据库性能会高些,吞吐量也会些!
  • 目录 一、笔者前言 二、正菜开始 三、假设你的服务1万...基本上来说,部分项目需要跟数据库做交互,那么,数据库连接池的大小设置成多合适呢? 一些开发老鸟可能还会告诉你:没关系,尽量设置的些...
  • 文章翻译整理自: ... 目录 一、笔者前言 ... 三、假设你的服务1万并发的访问 ... 四、为啥有这种效果?... 、其他应该考虑到的因素 ...基本上来说,部分项目需要跟数据库做交.
  • 如何正确设置数据库连接池

    千次阅读 2019-06-21 10:56:46
    目录 一、笔者前言 二、正菜开始 ...基本上来说,部分项目需要跟数据库做交互,那么,数据库连接池的大小设置成多合适呢? 一些开发老鸟可能还会告诉你:没关系,尽量设置的些,比如设置...
  • 从如何运用规范化原则到如何做成实际的数据库表,从如何保护数据库完整性到如何提高数据库的性能,从数据库的安全机制到并发事务控制,从数据库设计开发的常用模式到应用程序的数据访问策略,既理论又紧扣实践。...
  • 因为是稀疏索引,并不是每条日志都有索引记录它的偏移量,所以读取数据时要往前多读一些数据,防止漏读,等读到真正所需的数据时再真正给用户返回数据。 如下图,比如用户要读取25到43的日志,用二分法找25,找到的...
  • 情况是这样的:A在商店下了个单,选了四种毛钱的零食,每种只买了一袋,钱付完了结果订单查询后显示它只买了一种毛钱的零食,然而数据库中存的是他买了四种。 很明显,在SQL结果到Java的结果集映射过程出了...
  • 程序员工作第

    2018-07-17 13:40:45
    天了,和公司没有多的联系,就是安装了下平台vs2013,和数据库DB2,然后就花费我一天的时间就是昨天。虽然不影响我复习以前的知识,但是和项目一点联系没有,我心里其实感觉挺爽的,不用做事还不好? 但是...
  • 基本上来说,部分项目需要跟数据库做交互,那么,数据库连接池的大小设置成多合适呢? 一些开发老鸟可能还会告诉你:没关系,尽量设置的些,比如设置成 200,这样数据库性能会高些,吞吐量也会些! 你也许...
  • 互联网公司必问这个问题,要是一个连...随着互联网系统发展的逐步完善,提高系统的qps(每秒查询率),目前的绝部分系统增加了缓存机制从而避免请求过多的直接与数据库操作从而造成系统瓶颈,极的提升了用户体.
  • c、c++、Java、数据库MySQL、ORACLE、数据结构、计算机组成与原理、计算机网络、移动平台开发、语言啥都学、html、js、c#、vue也用过。 然后是讲毕设的构造,实现了哪些,巴拉巴拉,还有用了哪些技术,框架? 后台...
  • 没有想象当中的数据库、数据结构、网络……,大概20%跟word、ppt、excel关系,汉……总共题1,判断对错,20题20分,一般,昨晚感觉没变态地;2,单选,25题25分,后面很多是office平时使用的东西,...
  • 从Java基础、JavaWeb基础到常用的框架再到面试题都有完整的教程,几乎涵盖了Java后端必备的知识点。该开源仓库的文章都是我个人原创,公众号发过的技术文章(干货)也会有相关的目录整理,很多知识点我还在不停的...
  • 2020.9.6 ZYWL前端笔试

    2020-09-06 20:23:38
    部分就是数据库什么的,计算机网络基础好像没,还有一题问java里的一个什么。。。还有爬虫。。。恕我才疏学浅。我一学前端的,我要是会Java我学这干。。。而且所有题只能一往无前,没有“上一题”,只有“下一...
  • 疯狂的程序员

    热门讨论 2012-07-18 18:05:32
    “你不行,你连程序是啥都不懂。” “我不懂,你可以教我,你不是很牛B吗?” “那是,可是好多年没教书了。废了。” …… 绝影和他畅谈了一个下午,事情终于定了下来。那男人教绝影怎样做“程序员”,报酬是每节课...
  • 4.1.5 用过哪些Map类,都有什么区别,HashMap是线程安全的吗,并发下使用的Map是什么,他们内部原理分别是什么,比如存储方式,hashcode,扩容,默认容量等。 4.1.6 JAVA8的ConcurrentHashMap为什么放弃了分段锁,有...
  • 接下来说说我们的项目组,项目组由过度的加班熬夜许多同事来了又走,走了又来新同事,来了又走,如今只能招实习生了,都有五六个了,导致许多的员工没日没夜的加班熬夜干活,部分人呢没事也得没日没夜的加班发呆!...
  • 和华为的一位学长聊了很久,优秀的人果然都有过人之处 鲜衣怒马少年时,一日看尽长安花 24岁我全款买了人生的第一辆车 让你自制力提升300%的学习方法 读研or工作? 人生如水,由溪入海 提离职,涨薪 走,别回头 大学...
  • 可能的原因压力很,过度忧虑,紧张或焦虑,悲伤或抑郁,生气,容易出现睡眠问题。 吵闹的睡眠环境,睡眠环境过于明亮,污染,过度拥挤。 *****************************************************************...
  • 数据和结构完全定制,要啥有啥 看请求知结果,所求即所得 可一次获取任何数据、任何结构 能去除重复数据,节省流量提高速度 对于后端 提供通用接口,部分 API 不用再写 自动生成文档,不用再编写和维护 自动...
  • python字符串与绘图复习变量None变量参与运算没有赋值的情况不会改变绘制立方体绘制角星时间计算强化实现贷款计算连续输入多个字符串加法与绘图实现显示线段长度数据函数使用快速查阅函数帮助字符串三种风格字符与...

空空如也

空空如也

1 2
收藏数 29
精华内容 11
关键字:

五大数据库都有啥