一、问题背景
生产中磁盘占用很大,产生pgsql_tmp目录大约2T,整个磁盘使用率达到94%。
二、原因分析
1) 什么情况下会产生这个目录
正常情况下在默认表空间目录或特定表空间目录下不会有pgsql_tmp 目录,pgsql_tmp的官方文档说明:
查询要使用的内存超出work_mem的大小时(包括排序,DISTINCT,MERGE JOIN,HASH JOIN,笛卡尔积,哈希聚合,分组聚合,递归查询)等操作时会使用
临时文件来存储中间过程的数据。如果频繁的进行上述操作,临时文件将会快速增长,杀死对应pid执行的sql,或者重启后将清空所有临时文件,释放磁盘空间。
2)查找问题sql,发现都是通过Navicate客户端连接的sql,长时间(几小时甚至几天)还在运行,杀掉对应不合理SQL后,对应tmp文件自动删除
select * from pg_stat_activity where pid='98015';
select pg_terminate_backend (98015);
三、解决方法
1)设置pg相关参数
--1.每个进程临时文件空间的限制,如果超过改值,查询将取消,默认无限制
#temp_file_limit = -1 # limits per-process temp file space # in kB, or -1 for no limit
--2.当临时文件使用量大于设置阈值时,记录日志,默认不记录
#log_temp_files = -1 # log temporary files equal or larger
# than the specified size in kilobytes; # -1 disables, 0 logs all temp files
--3.当内存使用超过work_mem使用临时文件,设置合理work_mem大小
#work_mem (integer)
2)也可以设置会话超时参数,比如:statement_timemout=2H ,自动杀死异常慢sql
四、总结
- pg为了提高执行效率一些操作会使用内存代替临时存储,当内存不足时就会使用临时文件存储中间数据。
- 可酌情设置temp_file_limit 为磁盘空间的10%,当临时文件占用磁盘过高,自动取消该查询,记录查询语句 。
- 一般查询如果耗费大量的临时文件,有可能是没有索引导致,嵌套循环耗费cpu,磁盘io,以及临时文件占用高。
- 适当设置statement_timout参数,干掉长久执行的不合理的慢sql语句