执行计划没变,执行时快时慢是怎么回事?
时间:2025-11-05 09:24:29 出处:域名阅读(143)
今天遇到D-SMART产品本身的执行执行一个性能问题,我准备用D-SMART给一套Oracle数据库做个巡检,计划发现居然任务因为一条SQL超时而异常了。没变通过日志发现是时快时慢一条分析某个指标的SQL。


执行时间居然高达229秒,回事巡检报告中设定了SQL超时时间是执行执行180秒,而如果巡检的计划时间区间超过一个半月,则这条sql的没变执行时间介于170秒到250秒之间,就经常会超时了。时快时慢

D-SMART的回事后台数据库是PG,这张表是执行执行一张TIMESCALEDB的表。表上也创建了适当的计划索引。通过explain分析看,没变执行计划也是时快时慢正常的,通过这个分区索引做范围扫描,回事然后做聚合(Timescaledb会按照时间戳自动做数据分区)。通过D-SMART的PG数据库等待事件分析工具可以发现,数据文件读是排在前面的。站群服务器
刚开始的时候我也没有仔细分析,通过EXPAIN发现sort buffer使用量接近20M,明显超出了WORK_MEM参数。于是我调整了WORK_MEM参数,重新执行了这条SQL。发现原来需要200多秒的SQL不到50毫秒就完成了。不过我还是留了个心眼,因为D-SMART分析工具里可以看出文件读占了比较靠前的位置。于是我重启了一下PG数据库,再次执行这条SQL。比刚才稍微慢了一点,大概80多毫秒。不过比起200多秒来,也提升不少。于是我和同事说,这条SQL的性能问题解决了,加大WORK_MEM参数就可以了。
老储还是在PG上有丰富的实战经验,他提醒我,验证PG的问题,重启数据库是没用的企商汇,文件缓冲会影响SQL的性能。搞了二十多年Oracle,总是用Oracle的思维来思考现在的数据库问题,这回又犯了类似的错误。于是我重新做了测试,关闭数据库,然后使用echo 3 > drop_caches命令清除OS缓冲,然后再进行测试。
令人遗憾的是,SQL的性能又回到了从前,看样子加大WORK_MEM并没有有效的改善SQL性能。回过头来想想也是,哪怕因为排序缓冲超了一点,做了硬盘排序,也不可能有20秒的性能影响。
公司的这套PG 14.4的环境是装在一台虚拟机上的,IT技术网磁盘是SATA盘,性能确实不行。对于PG这样使用DOUBLE CACHE的数据库,文件缓冲确实可以对SQL性能有明显的帮助。而这种特性也会让PG数据库的同一条SQL语句在OS的不同状态下执行性能有较大的波动。下面我们通过一个例子来验证一下。
在做这个测试之前,我们先要安装一个插件-pgfincore,对这个插件有兴趣的朋友可以去https://github.com/klando/pgfincore 下载。Pgfincore是针对PG数据库的OS缓冲分析与操作的插件,一般被用户用来分析OS缓冲中的数据库表或者索引,也被部分用户用来预热数据,让部分热数据总是被缓冲在FILE CACHE中,从而让OS CACHE能够更好的发挥作用。
Pgfincore的功能十分强大,首先可以用来查看某张表或者索引在OS缓冲中的情况。比如:

我检查的一个timescaledb的索引分区,总共有15.7万个page,其中13.9万个page在OS缓冲里了。

第二个功能是把某张表或者索引的数据预热到OS CACHE里。这里要注意的是如果表是分区表,一定要直接预热分区,而不要使用表的名字,pgfincore不支持自动识别表分区。Timescaledb的一个表分区,原本这张表并没有完全被缓冲到内存里,通过调用pgfadvise_willneed函数,把这张表的所有数据都调用到OS缓冲中了。
第三个功能是备份和恢复某个场景下的OS CACHE。这对于一些十分关键的系统的预热十分有价值。比如说某个系统的某些热数据对于系统性能十分关键。当系统重启(特别是服务器重启)后的某个时间段里,数据没有预热完成之前,系统性能是会有较大影响的。如果我们在停机重启前,先备份OS CACHE中某些热表的缓冲情况,系统重启后立即预热这部分数据,则可以确保系统重启后立即恢复重启前的性能。

首先在系统重启前将pgfincore的数据保存在pgfincore_snapshot表中,系统重启后使用pgfadvise_loader重新装载缓冲数据。
有了上面的基础知识,我们下面就来做一个实验。

首先对OS缓冲做一个完全的清理。然后启动PG数据库。执行刚才有问题的那条SQL语句。

我只截取了部分执行计划,因为针对每个分区,都是相同的扫描方式,先对索引做扫描,然后再回表。这条SQL执行了34秒多。
接下来我们先按照上面的流程再次关闭数据库,清理缓冲,然后把所有的索引分区都先预热一下,看看效果如何。

可以看出,现在所有索引的OS缓冲项都是0,说明没有任何索引数据被缓存了。接下来预热,然后再次执行这条SQL。

大家可以看到,预热后,这些索引分区都在OS缓冲里了,同样再把所有的表的数据也预热一下。再来执行刚才的SQL语句:

大家可以看到,执行时间从34秒变成了31毫秒。实际上对于使用double cache的数据库来说,此类问题是十分常见的。此类数据库产品的同一条SQL在不同时间里执行的性能可能差异上百倍,但是其执行计划是完全相同的。这是因为DOUBLE CACHE的原因。Pgfincore插件为解决此类问题提供了一个很好的解决方案。利用snapshot/restore的方式,如果做一些适当的精细化管理,可以起到十分好的稳定关键业务SQL执行效率的作用。希望我的这个性能故障的案例能够给大家一些启示。
猜你喜欢
- 海氏烤箱(颠覆传统,轻松享受美食盛宴)
- 以赛睿7H耳机(挑战你的听觉极限,让音乐重焕生机!)
- 探索SonyZX770BT耳机的功能与性能(透析SonyZX770BT耳机的音质、舒适度与无线连接)
- 七彩虹1050显卡(解析七彩虹1050显卡的特点、优势和应用场景)
- 环境:Ubuntu8.04 1.安装build工具 sudo aptitude install build-essential linux-headers-$(uname -r) 2.安装readline zlib libncurses5 apt-get install zlib1g-dev apt-get install libreadline5 libreadline5-dev apt-get install libncurses5 libncurses5-dev 3.安装ruby ruby的源代码下载: http://www.ruby-lang.org/en/downloads/ wget ftp://ftp.ruby-lang.org/pub/ruby/1.8/ruby-1.8.6-p114.tar.gz tar xvfz ruby-1.8.6-p114.tar.gz cd ruby-1.8.6-p114 ./configure --prefix=/usr/local/ruby sudo make sudo make install 安装好以后,加入/usr/local/ruby/bin到操作系统的PATH环境变量中 编辑/etc/environment gedit /etc/environment 在最后面加入: PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/ bin:/sbin:/bin:/usr/games:/usr/local/ruby/bin 执行命令,使环境变量修改生效: source /etc/environment 4.安装gem wget http://rubyforge.org/frs/download.php/29548/rubygems-1.0.1.tgz tar xzvf rubygems-1.0.1.tgz cd rubygems-1.0.1 sudo ruby setup.rb 验证gem是否安装成功并升级 sudo gem update --system 5.安装rails sudo gem install rails --include-dependencies 安装好rails以后,验证是否安装成功,可以执行: rails –v 确认一下rails的版本。 //========================================= 其实openssl-ruby是ruby的扩展(extension),它不是像其他纯ruby代码一样,可以用gem来安装。一般情况下需要编译才行。 在linux系统下,这是经常碰到的问题,所以必须记住。 对于openssl-ruby的编译。 首先 cd ruby-source/ext/openssl ruby extconf.rb make make install 进行上面的操作需要包:libssl-dev //===================================================== gem mysql 的时候都要安装下面的包 sudo apt-get install libmysqlclient15-dev 也就是说 要编译安装公司的工具包需要操作如何: 1.安装build工具 sudo aptitude install build-essential linux-headers-$(uname -r) 2.安装readline zlib libncurses5 apt-get install zlib1g-dev apt-get install libreadline5 libreadline5-dev apt-get install libncurses5 libncurses5-dev 3.安装 libssl-dev apt-get install libssl-dev 4安装 mysql 编译包 sudo apt-get install libmysqlclient15-dev
- 梅捷主板质量如何?(一探梅捷主板的性能和可靠性)
- 长时间使用苹果手机充电会对电池造成什么影响?(探索苹果手机长时间充电的影响与解决办法)
- 昂达A58V手机的优缺点分析(一款实用性与性价比兼具的手机产品)
- 要想使用命令行安装和卸载软件,当然得事先知道要安装或卸载的软件包名称。而APT 是基于Debian 的Linux 发行版(包括Ubuntu)包管理命令,使用 apt-cache 我们便可以找出系统中包相关的元数据信息,本文中将就将向大家介绍如何查看Ubuntu 安装包信息。使用apt-cache假如要列出 Ubuntu 系统中所有可用的软件包,我们只需执行如下命令:复制代码代码如下:apt-cache pkgnames | less该命令中的 | less 管道输出,可以让我们在数据较多时通过上、下箭头或“PgUp” 及“PgDn” 来滚动查看。当我们不找到所需包名或不需要滚动查看时,只需按 q 即可退出。假如你知道软件包名的开头字符,我们便可以使用搜索功能来缩小范围。例如要查看Firefox 的包名,则可使用类似如下命令:复制代码代码如下:apt-cache pkgnames firef 使用上述命令,我们便可以查看到所有以 firef 开头的软件包。当我们知道包名后,要显示软件包的详细信息,例如:版本号、大小、校验值和软件描述等信息时,则可使用 show 选项来进行查看:复制代码代码如下:apt-cache show firefox 当大家要查看某个软件包所需依赖及哪些包依赖于该软件包时,则需要使用 showpkg 选项:复制代码代码如下:apt-cache showpkg firefox 当我们需要查看当前 Ubuntu 不同类型包的统计及整体统计信息时,可以使用 stats 选项:复制代码代码如下:apt-cache stats 要了解某个软件包的迁移及相关说明时,我们可以使用search 选项:复制代码代码如下:apt-cache search firefox-locale-zh-hans 使用axi-cacheaxi-cache 可以算是apt-cache 命令的孪生兄弟,但它可以提供的描述信息和相关性更强。我们还是以Firefox 来举个例子:复制代码代码如下:axi-cache search firef 该命令默认中显示20条结果:查看更多信息可使用如下命令:复制代码代码如下:axi-cache more 以上就是告诉大家Ubuntu安装包信息是如何查看的,希望该文对大家的学习有所帮助。