PostgreSQL一条SQL引发系统out of memory

简介: 错误描述(1) Postgres执行的原SQL:select COALESCE(m1.place_id, m2.place_id, m3.place_id) as place_id, concat_ws('``', m1.

错误描述

(1) Postgres执行的原SQL

select COALESCE(m1.place_id, m2.place_id, m3.place_id) as place_id, concat_ws('``', m1.rich_attributes, m2.rich_attributes, m3.rich_attributes) as rich_attributes from
(SELECT place_external_points.place_id, string_agg(concat(place_external_points.metadata_dictionary_id, '@-@', place_external_points.value), '``'::text) AS rich_attributes
FROM place_external_points b WHERE metadata_dictionary_id = ANY (ARRAY[61, 62]) group by place_external_points.place_id) m1
full join
(SELECT place_geocoded.place_id, string_agg(concat(place_geocoded.metadata_dictionary_id, '@-@', place_geocoded.value), '``'::text) AS rich_attributes FROM place_geocoded g
WHERE metadata_dictionary_id = ANY (ARRAY[70, 71, 72, 73, 74, 75, 76, 77, 78]) group by place_geocoded.place_id) m2 on m1.place_id = m2.place_id
full join
(SELECT place_attributes.place_id, string_agg(concat(place_attributes.metadata_dictionary_id, '@-@', place_attributes.value), '``'::text) AS rich_attributes FROM
place_attributes a WHERE place_attributes.metadata_dictionary_id = ANY (ARRAY[5, 7, 9, 10, 11, 12, 13, 33, 35, 46, 51, 52, 53, 54, 55, 57, 58, 59]) group by a.place_id) m3 on m2.place_id = m3.place_id;


(2) 系统日志message:

Dec 27 10:39:13 shb-postgresql-01 kernel: Out of memory: Kill process 9116 (postgres) score 823 or sacrifice child

Dec 27 10:39:13 shb-postgresql-01 kernel: Killed process 9116, UID 501, (postgres) total-vm:40440476kB, anon-rss:28320224kB, file-rss:2154596kB

Dec 27 10:39:13 shb-postgresql-01 kernel: postgres: page allocation failure. order:0, mode:0x280da

Dec 27 10:39:13 shb-postgresql-01 kernel: Pid: 9116, comm: postgres Not tainted 2.6.32-431.el6.x86_64 #1


(3) 数据库日志:

less /usr/local/pgsql/data/pg_log/postgresql-2017-12-29_000000.log
WARNING:  terminating connection because of crash of another server process
DETAIL:  The postmaster has commanded this server process to roll back the current transaction and exit, because another server process exited abnormally and possibly corrupted shared memory.
HINT:  In a moment you should be able to reconnect to the database and repeat your command.
FATAL:  the database system is in recovery mode
LOG:  all server processes terminated; reinitializing
LOG:  database system was interrupted; last known up at 2017-12-29 09:20:36 CST
FATAL:  the database system is in recovery mode
FATAL:  the database system is in recovery mode
FATAL:  the database system is in recovery mode
FATAL:  the database system is in recovery mode
FATAL:  the database system is in recovery mode
FATAL:  the database system is in recovery mode
FATAL:  the database system is in recovery mode
LOG:  database system was not properly shut down; automatic recovery in progress
LOG:  invalid record length at 94A/478309C0
LOG:  redo is not required
LOG:  MultiXact member wraparound protections are now enabled
LOG:  database system is ready to accept connections
LOG:  autovacuum launcher started



(4) 脚本运行的时候内存变化:

# free -g

total       used       free     shared    buffers     cached

Mem:            31         31          0          0          0          0

-/+ buffers/cache:         31          0

Swap:            7          3          4


原因:通过以上信息可以发现是postgres的查询SQL把内存消耗殆尽,并且开始使用swap分区,导致系统发生oom-kill,数据库进程被干掉,然后重启恢复。



分析过程


(1) 表place_external_points和place_geocoded经查看都为空,表place_attributes有1亿多条数据,所以问题发生在最后一条select xxx from  place_attributes语句上,这个表的列metadata_dictionary_id有对应的索引

# \d place_attributes;
       Table "denali_search_cn_17q3_20171226_epl.place_attributes"
         Column         |              Type              |   Modifiers   
------------------------+--------------------------------+---------------
place_id               | integer                        |
metadata_dictionary_id | integer                        |
value                  | text                           |
lang                   | character varying(50)          |
source                 | character varying(50)          |
create_time            | timestamp(6) without time zone | default now()
update_time            | timestamp(6) without time zone |
Indexes:
    "place_attributes_metadata_dictionary_id_idx" btree (metadata_dictionary_id)
    "place_attributes_place_id_metadata_dictionary_id_idx" btree (place_id, metadata_dictionary_id)
    "place_attributes_value_idx" btree (value)


    

(2) 通过执行计划explain发现使用了hash聚合:hashaggregate,SQL本身是group by ,没有使用group聚合,却使用了hash聚合,可初步判断数据库执行计划不是最优的:

# explain SELECT place_id, string_agg(concat(metadata_dictionary_id, '@-@', value), '``'::text) AS rich_attributes FROM place_attributes WHERE metadata_dictionary_id = ANY (ARRAY[5, 7, 9, 10, 11, 12, 13, 33, 35, 46, 51, 52, 53, 54, 55, 57, 58, 59]) group by place_attributes.place_id;
                                                             QUERY PLAN                                                             
------------------------------------------------------------------------------------------------------------------------------------
HashAggregate  (cost=7622781.80..7985216.03 rows=323575 width=62)
   Group Key: place_id
   ->  Sort  (cost=7622781.80..7712379.18 rows=35838955 width=62)
         Sort Key: place_id
         ->  Bitmap Heap Scan on place_attributes  (cost=450351.86..2452151.90 rows=35838955 width=62)
               Recheck Cond: (metadata_dictionary_id = ANY ('{5,7,9,10,11,12,13,33,35,46,51,52,53,54,55,57,58,59}'::integer[]))
               ->  Bitmap Index Scan on place_attributes_metadata_dictionary_id_idx  (cost=0.00..441392.12 rows=35838955 width=0)
                     Index Cond: (metadata_dictionary_id = ANY ('{5,7,9,10,11,12,13,33,35,46,51,52,53,54,55,57,58,59}'::integer[]))


解决方法


更新统计分析然后选择最优的执行计划

(Updates statistics used by the planner to determine the most efficient way to execute a query.)

postgres=# vacuum analyze place_attributes;


或者临时关闭enable_hashagg:

(Enables or disables the query planner's use of hashed aggregation plan types. The default is on)

# set  enable_hashagg =0;


再次查看执行计划,发现执行计划不再走hashaggregate

yangzi=# explain SELECT place_id, string_agg(concat(metadata_dictionary_id, '@-@', value), '``'::text) AS rich_attributes FROM place_attributes WHERE metadata_dictionary_id = ANY (ARRAY[5, 7, 9, 10, 11, 12, 13, 33, 35, 46, 51, 52, 53, 54, 55, 57, 58, 59]) group by place_attributes.place_id;
                                                             QUERY PLAN                                                             
------------------------------------------------------------------------------------------------------------------------------------
GroupAggregate  (cost=7622781.80..7985216.03 rows=323575 width=62)
   Group Key: place_id
   ->  Sort  (cost=7622781.80..7712379.18 rows=35838955 width=62)
         Sort Key: place_id
         ->  Bitmap Heap Scan on place_attributes  (cost=450351.86..2452151.90 rows=35838955 width=62)
               Recheck Cond: (metadata_dictionary_id = ANY ('{5,7,9,10,11,12,13,33,35,46,51,52,53,54,55,57,58,59}'::integer[]))
               ->  Bitmap Index Scan on place_attributes_metadata_dictionary_id_idx  (cost=0.00..441392.12 rows=35838955 width=0)
                     Index Cond: (metadata_dictionary_id = ANY ('{5,7,9,10,11,12,13,33,35,46,51,52,53,54,55,57,58,59}'::integer[]))



最后再去执行原SQL,没有报错,并且很快完成。

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍如何基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
目录
相关文章
|
12月前
|
关系型数据库 MySQL 数据库
阿里云数据库RDS费用价格:MySQL、SQL Server、PostgreSQL和MariaDB引擎收费标准
阿里云RDS数据库支持MySQL、SQL Server、PostgreSQL、MariaDB,多种引擎优惠上线!MySQL倚天版88元/年,SQL Server 2核4G仅299元/年,PostgreSQL 227元/年起。高可用、可弹性伸缩,安全稳定。详情见官网活动页。
1747 152
|
12月前
|
关系型数据库 MySQL 数据库
阿里云数据库RDS支持MySQL、SQL Server、PostgreSQL和MariaDB引擎
阿里云数据库RDS支持MySQL、SQL Server、PostgreSQL和MariaDB引擎,提供高性价比、稳定安全的云数据库服务,适用于多种行业与业务场景。
1161 156
|
SQL 关系型数据库 MySQL
Go语言数据库编程:使用 `database/sql` 与 MySQL/PostgreSQL
Go语言通过`database/sql`标准库提供统一数据库操作接口,支持MySQL、PostgreSQL等多种数据库。本文介绍了驱动安装、连接数据库、基本增删改查操作、预处理语句、事务处理及错误管理等内容,涵盖实际开发中常用的技巧与注意事项,适合快速掌握Go语言数据库编程基础。
1667 213
|
12月前
|
关系型数据库 分布式数据库 数据库
阿里云数据库收费价格:MySQL、PostgreSQL、SQL Server和MariaDB引擎费用整理
阿里云数据库提供多种类型,包括关系型与NoSQL,主流如PolarDB、RDS MySQL/PostgreSQL、Redis等。价格低至21元/月起,支持按需付费与优惠套餐,适用于各类应用场景。
|
SQL 容灾 安全
云时代SQL Server的终极答案:阿里云 RDS SQL Server如何用异地容灾重构系统可靠性
在数字化转型的浪潮中,数据库的高可用性已成为系统稳定性的生命线。作为经历过多次生产事故的资深开发者,肯定深知传统自建SQL Server架构的脆弱性——直到遇见阿里云 RDS SQL Server,其革命性的异地容灾架构彻底改写了游戏规则。
|
SQL 关系型数据库 PostgreSQL
CTE vs 子查询:深入拆解PostgreSQL复杂SQL的隐藏性能差异
本文深入探讨了PostgreSQL中CTE(公共表表达式)与子查询的选择对SQL性能的影响。通过分析两者底层机制,揭示CTE的物化特性及子查询的优化融合优势,并结合多场景案例对比执行效率。最终给出决策指南,帮助开发者根据数据量、引用次数和复杂度选择最优方案,同时提供高级优化技巧和版本演进建议,助力SQL性能调优。
1555 1
|
SQL 关系型数据库 OLAP
云原生数据仓库AnalyticDB PostgreSQL同一个SQL可以实现向量索引、全文索引GIN、普通索引BTREE混合查询,简化业务实现逻辑、提升查询性能
本文档介绍了如何在AnalyticDB for PostgreSQL中创建表、向量索引及混合检索的实现步骤。主要内容包括:创建`articles`表并设置向量存储格式,创建ANN向量索引,为表增加`username`和`time`列,建立BTREE索引和GIN全文检索索引,并展示了查询结果。参考文档提供了详细的SQL语句和配置说明。
721 2
|
SQL 存储 数据库
SQL在构建系统中的应用:关键要素与编写技巧
在构建基于数据库的系统时,SQL(Structured Query Language)扮演着至关重要的角色
|
SQL 数据库连接 数据库
管理系统中的Visual Studio与SQL集成技巧与方法
在现代软件开发和管理系统中,Visual Studio(VS)作为强大的集成开发环境(IDE),与SQL数据库的紧密集成是构建高效、可靠应用程序的关键

推荐镜像

更多