标签

PostgreSQL , effective_io_concurrency , 异步IO


背景

异步IO的目的是充分发挥块设备的吞吐能力,让块设备处于更繁忙的工作状态(一次连续摄取更多的块),而不是等用户进程需要数据时再读取。

如果数据库并发连接(或者活跃会话)足够时,并且块设备处于繁忙状态,那么没有必要开启异步IO,因为开了也没什么用,块设备已经足够的忙了。

目前PostgreSQL的bitmap heap scan支持异步IO,因为bitmap heap scan是按顺序读取堆表的数据块的,对于机械硬盘,bitmap heap scan异步IO效率可以得到充分的发挥。(实际上全表扫描也适合异步IO。)

异步IO的参数effective_io_concurrency,应该如何设置呢?

如果是磁盘阵列,根据表空间所在的块设备进行设置,例如RAID0, RAID10,设置为磁盘个数,而RAID5或者其他RAID,设置为实际的数据盘个数(如,raid5(10)设置为9)。

如果设置为0,表示不使用异步IO。

仅仅当操作系统支持posix时,才能使用异步IO。

effective_io_concurrency (integer)  Sets the number of concurrent disk I/O operations that PostgreSQL expects can be executed simultaneously.
Raising this value will increase the number of I/O operations that any individual PostgreSQL session attempts to initiate in parallel.
The allowed range is 1 to 1000, or zero to disable issuance of asynchronous I/O requests. Currently, this setting only affects bitmap heap scans.  For magnetic drives, a good starting point for this setting is the number of separate drives comprising a RAID 0 stripe or RAID 1 mirror being used for the database.
(For RAID 5 the parity drive should not be counted.)
However, if the database is often busy with multiple queries issued in concurrent sessions, lower values may be sufficient to keep the disk array busy.
A value higher than needed to keep the disks busy will only result in extra CPU overhead.
SSDs and other memory-based storage can often process many concurrent requests, so the best value might be in the hundreds.  Asynchronous I/O depends on an effective posix_fadvise function, which some operating systems lack.
If the function is not present then setting this parameter to anything but zero will result in an error.
On some operating systems (e.g., Solaris), the function is present but does not actually do anything.  The default is 1 on supported systems, otherwise 0.
This value can be overridden for tables in a particular tablespace by setting the tablespace parameter of the same name (see ALTER TABLESPACE).

那么生产中应该如何设置呢?

我们实际测试一下,如果是SSD,从测试结果看,建议关闭异步IO。(虽然手册中提到如果是内存盘或SSD盘,可以设置更大的值,但是实测效果不理想。)

测试用例

src/test/regress/expected/select_parallel.out

-- test parallel bitmap heap scan.
set enable_seqscan to off;
set enable_indexscan to off;
set enable_hashjoin to off;
set enable_mergejoin to off;
set enable_material to off;
-- test prefetching, if the platform allows it
DO $$
BEGIN  SET effective_io_concurrency = 50;
EXCEPTION WHEN invalid_parameter_value THEN
END $$;
set work_mem='64kB';  --set small work mem to force lossy pages
explain (costs off)  select count(*) from tenk1, tenk2 where tenk1.hundred > 1 and tenk2.thousand=0;  QUERY PLAN
------------------------------------------------------------  Aggregate  ->  Nested Loop  ->  Seq Scan on tenk2  Filter: (thousand = 0)  ->  Gather  Workers Planned: 4  ->  Parallel Bitmap Heap Scan on tenk1  Recheck Cond: (hundred > 1)  ->  Bitmap Index Scan on tenk1_hundred  Index Cond: (hundred > 1)
(10 rows)  select count(*) from tenk1, tenk2 where tenk1.hundred > 1 and tenk2.thousand=0;  count
-------  98000
(1 row)  create table bmscantest (a int, t text);
insert into bmscantest select r, 'fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo' FROM generate_series(1,100000) r;
create index i_bmtest ON bmscantest(a);
select count(*) from bmscantest where a>1;  count
-------  99999
(1 row)  reset enable_seqscan;
reset enable_indexscan;
reset enable_hashjoin;
reset enable_mergejoin;
reset enable_material;
reset effective_io_concurrency;
reset work_mem;
drop table bmscantest;

测试

postgres=# select pg_backend_pid();  pg_backend_pid
----------------  42328
(1 row)  postgres=# set enable_seqscan=off;
SET
postgres=# set enable_indexscan=off;
SET
postgres=# set work_mem ='64kB';
SET
postgres=# set max_parallel_workers_per_gather =0;
SET  postgres=# explain (analyze,verbose,timing,costs,buffers) select count(*) from ptest where id>1000 ;  QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------------  Aggregate  (cost=338227.11..338227.12 rows=1 width=8) (actual time=2634.805..2634.806 rows=1 loops=1)  Output: count(*)  Buffers: shared hit=110649  ->  Bitmap Heap Scan on public.ptest  (cost=104910.47..313230.01 rows=9998843 width=0) (actual time=418.257..1735.802 rows=9999000 loops=1)  Output: id, info  Recheck Cond: (ptest.id > 1000)  Rows Removed by Index Recheck: 40  Heap Blocks: exact=408 lossy=82918  Buffers: shared hit=110649  ->  Bitmap Index Scan on idx_ptest1  (cost=0.00..102410.76 rows=9998843 width=0) (actual time=418.158..418.158 rows=9999000 loops=1)  Index Cond: (ptest.id > 1000)  Buffers: shared hit=27323  Planning time: 0.123 ms  Execution time: 2634.858 ms
(14 rows)  postgres=# set effective_io_concurrency =0;
SET
postgres=# explain (analyze,verbose,timing,costs,buffers) select count(*) from ptest where id>1000 ;  QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------------  Aggregate  (cost=338227.11..338227.12 rows=1 width=8) (actual time=2619.868..2619.869 rows=1 loops=1)  Output: count(*)  Buffers: shared hit=110649  ->  Bitmap Heap Scan on public.ptest  (cost=104910.47..313230.01 rows=9998843 width=0) (actual time=418.974..1721.578 rows=9999000 loops=1)  Output: id, info  Recheck Cond: (ptest.id > 1000)  Rows Removed by Index Recheck: 40  Heap Blocks: exact=408 lossy=82918  Buffers: shared hit=110649  ->  Bitmap Index Scan on idx_ptest1  (cost=0.00..102410.76 rows=9998843 width=0) (actual time=418.873..418.873 rows=9999000 loops=1)  Index Cond: (ptest.id > 1000)  Buffers: shared hit=27323  Planning time: 0.155 ms  Execution time: 2619.930 ms
(14 rows)  postgres=# set effective_io_concurrency =1000;
SET
postgres=# explain (analyze,verbose,timing,costs,buffers) select count(*) from ptest where id>1000 ;  QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------------  Aggregate  (cost=338227.11..338227.12 rows=1 width=8) (actual time=2661.584..2661.585 rows=1 loops=1)  Output: count(*)  Buffers: shared hit=110649  ->  Bitmap Heap Scan on public.ptest  (cost=104910.47..313230.01 rows=9998843 width=0) (actual time=417.591..1761.522 rows=9999000 loops=1)  Output: id, info  Recheck Cond: (ptest.id > 1000)  Rows Removed by Index Recheck: 40  Heap Blocks: exact=408 lossy=82918  Buffers: shared hit=110649  ->  Bitmap Index Scan on idx_ptest1  (cost=0.00..102410.76 rows=9998843 width=0) (actual time=417.473..417.473 rows=9999000 loops=1)  Index Cond: (ptest.id > 1000)  Buffers: shared hit=27323  Planning time: 0.113 ms  Execution time: 2661.632 ms
(14 rows)  postgres=# set max_parallel_workers_per_gather =4;
SET
postgres=# set effective_io_concurrency =1000;
SET
postgres=# explain (analyze,verbose,timing,costs,buffers) select count(*) from ptest where id>1000 ;  QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------------------------------  Finalize Aggregate  (cost=226740.55..226740.56 rows=1 width=8) (actual time=1017.452..1017.452 rows=1 loops=1)  Output: count(*)  Buffers: shared hit=111309  ->  Gather  (cost=226740.13..226740.54 rows=4 width=8) (actual time=1017.350..1017.447 rows=5 loops=1)  Output: (PARTIAL count(*))  Workers Planned: 4  Workers Launched: 4  Buffers: shared hit=111309  ->  Partial Aggregate  (cost=225740.13..225740.14 rows=1 width=8) (actual time=1014.227..1014.227 rows=1 loops=5)  Output: PARTIAL count(*)  Buffers: shared hit=110649  Worker 0: actual time=1013.492..1013.492 rows=1 loops=1  Buffers: shared hit=16355  Worker 1: actual time=1013.497..1013.497 rows=1 loops=1  Buffers: shared hit=16269  Worker 2: actual time=1013.510..1013.510 rows=1 loops=1  Buffers: shared hit=16333  Worker 3: actual time=1013.501..1013.501 rows=1 loops=1  Buffers: shared hit=16268  ->  Parallel Bitmap Heap Scan on public.ptest  (cost=104910.47..219490.85 rows=2499711 width=0) (actual time=418.784..840.764 rows=1999800 loops=5)  Recheck Cond: (ptest.id > 1000)  Rows Removed by Index Recheck: 8  Heap Blocks: exact=92 lossy=18009  Buffers: shared hit=110649  Worker 0: actual time=417.217..844.848 rows=1962600 loops=1  Buffers: shared hit=16355  Worker 1: actual time=422.223..844.926 rows=1952280 loops=1  Buffers: shared hit=16269  Worker 2: actual time=417.216..844.028 rows=1959960 loops=1  Buffers: shared hit=16333  Worker 3: actual time=417.216..840.404 rows=1952080 loops=1  Buffers: shared hit=16268  ->  Bitmap Index Scan on idx_ptest1  (cost=0.00..102410.76 rows=9998843 width=0) (actual time=419.867..419.867 rows=9999000 loops=1)  Index Cond: (ptest.id > 1000)  Buffers: shared hit=27323  Planning time: 0.121 ms  Execution time: 1027.083 ms
(37 rows)
postgres=# set effective_io_concurrency =1;
SET
postgres=# explain (analyze,verbose,timing,costs,buffers) select count(*) from ptest where id>1000 ;  QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------------------------------  Finalize Aggregate  (cost=226740.55..226740.56 rows=1 width=8) (actual time=1006.182..1006.182 rows=1 loops=1)  Output: count(*)  Buffers: shared hit=111309  ->  Gather  (cost=226740.13..226740.54 rows=4 width=8) (actual time=1006.073..1006.177 rows=5 loops=1)  Output: (PARTIAL count(*))  Workers Planned: 4  Workers Launched: 4  Buffers: shared hit=111309  ->  Partial Aggregate  (cost=225740.13..225740.14 rows=1 width=8) (actual time=1003.124..1003.124 rows=1 loops=5)  Output: PARTIAL count(*)  Buffers: shared hit=110649  Worker 0: actual time=1002.447..1002.447 rows=1 loops=1  Buffers: shared hit=16408  Worker 1: actual time=1002.441..1002.441 rows=1 loops=1  Buffers: shared hit=16312  Worker 2: actual time=1002.446..1002.446 rows=1 loops=1  Buffers: shared hit=16093  Worker 3: actual time=1002.436..1002.436 rows=1 loops=1  Buffers: shared hit=16287  ->  Parallel Bitmap Heap Scan on public.ptest  (cost=104910.47..219490.85 rows=2499711 width=0) (actual time=413.650..828.524 rows=1999800 loops=5)  Recheck Cond: (ptest.id > 1000)  Rows Removed by Index Recheck: 8  Heap Blocks: exact=85 lossy=18141  Buffers: shared hit=110649  Worker 0: actual time=412.974..833.142 rows=1968960 loops=1  Buffers: shared hit=16408  Worker 1: actual time=412.994..831.530 rows=1957440 loops=1  Buffers: shared hit=16312  Worker 2: actual time=412.980..831.353 rows=1931160 loops=1  Buffers: shared hit=16093  Worker 3: actual time=412.977..828.009 rows=1954440 loops=1  Buffers: shared hit=16287  ->  Bitmap Index Scan on idx_ptest1  (cost=0.00..102410.76 rows=9998843 width=0) (actual time=416.164..416.164 rows=9999000 loops=1)  Index Cond: (ptest.id > 1000)  Buffers: shared hit=27323  Planning time: 0.124 ms  Execution time: 1015.976 ms
(37 rows)  postgres=# set effective_io_concurrency =0;
SET
postgres=# explain (analyze,verbose,timing,costs,buffers) select count(*) from ptest where id>1000 ;  QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------------------------------  Finalize Aggregate  (cost=226740.55..226740.56 rows=1 width=8) (actual time=943.288..943.288 rows=1 loops=1)  Output: count(*)  Buffers: shared hit=111309  ->  Gather  (cost=226740.13..226740.54 rows=4 width=8) (actual time=943.170..943.282 rows=5 loops=1)  Output: (PARTIAL count(*))  Workers Planned: 4  Workers Launched: 4  Buffers: shared hit=111309  ->  Partial Aggregate  (cost=225740.13..225740.14 rows=1 width=8) (actual time=940.060..940.060 rows=1 loops=5)  Output: PARTIAL count(*)  Buffers: shared hit=110649  Worker 0: actual time=939.276..939.276 rows=1 loops=1  Buffers: shared hit=16286  Worker 1: actual time=939.387..939.388 rows=1 loops=1  Buffers: shared hit=16303  Worker 2: actual time=939.389..939.390 rows=1 loops=1  Buffers: shared hit=16291  Worker 3: actual time=939.388..939.389 rows=1 loops=1  Buffers: shared hit=15943  ->  Parallel Bitmap Heap Scan on public.ptest  (cost=104910.47..219490.85 rows=2499711 width=0) (actual time=419.160..766.586 rows=1999800 loops=5)  Recheck Cond: (ptest.id > 1000)  Rows Removed by Index Recheck: 8  Heap Blocks: exact=92 lossy=18411  Buffers: shared hit=110649  Worker 0: actual time=418.404..771.100 rows=1954320 loops=1  Buffers: shared hit=16286  Worker 1: actual time=418.487..770.127 rows=1956360 loops=1  Buffers: shared hit=16303  Worker 2: actual time=418.491..770.200 rows=1954920 loops=1  Buffers: shared hit=16291  Worker 3: actual time=418.513..768.309 rows=1913160 loops=1  Buffers: shared hit=15943  ->  Bitmap Index Scan on idx_ptest1  (cost=0.00..102410.76 rows=9998843 width=0) (actual time=421.750..421.750 rows=9999000 loops=1)  Index Cond: (ptest.id > 1000)  Buffers: shared hit=27323  Planning time: 0.169 ms  Execution time: 952.028 ms
(37 rows)

分别使用perf record -ag -p $pid 进行了跟踪。因为这个版本编译时没有打开几个需要的开关(-g -ggdb -fno-omit-frame-pointer),所以看不出什么问题。用户可以自己测试并分析一下。

参考

《PostgreSQL on Linux 最佳部署手册》

《Linux 性能诊断 perf使用指南》

《PostgreSQL 源码性能诊断(perf profiling)指南》

https://www.postgresql.org/docs/devel/static/runtime-config-resource.html

src/backend/executor/nodeBitmapHeapscan.c

PostgreSQL 异步IO实测相关推荐

  1. 操作系统与存储:解析Linux内核全新异步IO引擎io_uring设计与实现

    作者:draculaqian,腾讯后台开发工程师 引言 存储场景中,我们对性能的要求非常高.在存储引擎底层的IO技术选型时,可能会有如下讨论关于IO的讨论. http://davmac.org/dav ...

  2. python 异步io_Python中的异步IO:完整的演练

    python 异步io Async IO is a concurrent programming design that has received dedicated support in Pytho ...

  3. 协程和任务 异步IO 重点

    20210815 https://mp.weixin.qq.com/s/XeHaWhKztnCOIXb_2GSitQ https://mp.weixin.qq.com/s/lnox3pbpzJ2kWl ...

  4. 2021年大数据Flink(四十六):扩展阅读 异步IO

    目录 扩展阅读  异步IO 介绍 异步IO操作的需求 使用Aysnc I/O的前提条件 Async I/O API 案例演示 扩展阅读 原理深入 AsyncDataStream 消息的顺序性 扩展阅读 ...

  5. Node的异步与java的异步_node中异步IO的理解

    解释性语言和编译型语言的区别: 计算器不能直接的理解高级语言,只能理解机器语言,所以必须把高级语言翻译为机器语言,翻译的方式有两种,一个是编译,一个是解释. 解释性语言的程序不需要编译,它是在运行程序 ...

  6. 【网络编程】同步IO、异步IO、阻塞IO、非阻塞IO

    IO分两阶段: 1.数据准备阶段:在该阶段,根据是否等待数据准备,将IO分成阻塞和非阻塞: 2.内核空间复制回用户进程缓冲区阶段:在该阶段,只要程序需要等待复制完成,才能往下运行(尽管这个时间很短), ...

  7. 异步IO一定更好吗?

    http://cnodejs.org/blog/?p=1015 续:异步IO一定更好吗? 我之前的一篇文章<异步IO一定更好吗?>中举了一个很变态的例子,用以说明在单碟机械式硬盘上异步IO ...

  8. Python之路-python(Queue队列、进程、Gevent协程、Select\Poll\Epoll异步IO与事件驱动)

    一.进程: 1.语法 2.进程间通讯 3.进程池 二.Gevent协程 三.Select\Poll\Epoll异步IO与事件驱动 一.进程: 1.语法 1 简单的启动线程语法 2 def run(na ...

  9. python asyncio教程_python中使用asyncio实现异步IO实例分析

    1.说明 Python实现异步IO非常简单,asyncio是Python 3.4版本引入的标准库,直接内置了对异步IO的支持. asyncio的编程模型就是一个消息循环.我们从asyncio模块中直接 ...

最新文章

  1. 沉痛悼念游戏开发大神毛星云
  2. latex 特殊符号
  3. 成功解决This module was deprecated in version 0.18 in favor of the model_selection module into which all
  4. SAP Analytics Cloud的Sample Story
  5. 130242014022 蓝宏铮 第2次实验
  6. Android之版本检测和更新
  7. 博客园-我的新的开始
  8. GMQ钱包致力成为您数字资产安全的保护伞
  9. merge合并两个有序数组
  10. 仿途牛旅游APP项目开发
  11. R语言︱情感分析—词典型代码实践(最基础)(一)
  12. 设置货币值中使用的小数位数
  13. 【C++】对象作为函数参数【原创技术】
  14. 一文整理总结常见Java后端面试题系列——Spring篇(2022最新版)
  15. 电脑游戏测试cpugpu软件,【七彩虹GTX760评测】七彩虹iGame760烈焰战神规格介绍-中关村在线...
  16. 使用python画等边三角形的程序-python叠加等边三角形的代码编写方法
  17. CH341A及XTW 2两种SPI FLASH烧录器的硬件使用说明_20220920【可用于升级主板BIOS】
  18. 服务器响应551,为什么输出fi上的ftp响应551错误
  19. 载谭 Binomial Sum:多项式复合、插值与泰勒展开
  20. pdf合到一起java_如何将两个PDF文件合并成一个Java?

热门文章

  1. java IDE的四大金刚
  2. Spark2.1.0分布式集群安装
  3. LOJ504「LibreOJ β Round」ZQC 的手办
  4. String字符串类的获取功能
  5. Struts2 单个文件上传/多文件上传
  6. 解决:请购买WinRAR许可,您注册还剩下40天(WinRAR老是弹出烦人的对话框)
  7. WEB高性能开发(10) - 疯狂的HTML压缩
  8. 《LeetCode力扣练习》第155题 最小栈 Java
  9. 2021高考成绩一分段查询陕西省,2021年陕西高考一分一段表查询排名方法 成绩排名位次什么时候公布...
  10. python爬取学校题库_如何使用 Python 爬虫爬取牛客网 Java 题库?