PostgreSQL后端处理高内存使用问题

PostgreSQL后端处理高内存使用问题,第1张

概述我们正在评估使用PostgreSQL实现多租户数据库, 目前,我们正在对单数据库多模式模型进行一些测试 (基本上,所有租户在同一数据库中拥有相同的数据库对象集,然后在自己的模式下). 应用程序将维护一个将在所有租户/模式之间共享的连接池. 例如如果数据库有500个租户/模式,每个租户有200个表/视图, 表/视图的总数将为500 * 200 = 100,000. 由于连接池将由所有租户使用,因此最 我们正在评估使用Postgresql实现多租户数据库,
目前,我们正在对单数据库多模式模型进行一些测试
(基本上,所有租户在同一数据库中拥有相同的数据库对象集,然后在自己的模式下).
应用程序将维护一个将在所有租户/模式之间共享的连接池.

例如如果数据库有500个租户/模式,每个租户有200个表/视图,
表/视图的总数将为500 * 200 = 100,000.

由于连接池将由所有租户使用,因此最终每个连接都将命中所有表/视图.

在我们的测试中,当连接访问更多视图时,我们发现后端进程的内存使用量增长非常快,并且大多数都是私有内存.
这些内存将保持不变直到连接关闭.

我们有一个测试用例,一个后端进程使用更多的30GB内存,最终得到内存不足错误.

为了帮助理解这个问题,我编写了代码来创建简化的测试用例
– MTDB_destroy:用于清除租户模式
– MTDB_Initialize:用于创建多租户DB
– MTDB_RunTests:简化的测试用例,基本上从所有租户视图中逐一选择.

我所做的测试是在CentOS 5.4上的Postgresql 9.0.3上进行的

为了确保我有一个干净的环境,我重新创建了数据库集群并将大多数配置保留为默认值,
(我唯一需要改变的是增加“max_locks_per_transaction”,因为MTDB_destroy需要丢弃许多对象.)

这就是我重现这个问题的方法:

>创建一个新数据库
>使用附加的代码创建三个函数
>连接到新创建的数据库并运行初始化脚本

– 初始化

选择MTDB_Initialize(‘tenant’,100,true);

– 不确定真空分析在这里是否有用,我只是运行它

真空分析;

– 检查创建的表/视图

从information_schema.tables中选择table_schema,table_type,count(*),其中table_schema类似于’tenant%’group by table_schema,table_type order by table_schema,table_type;
>打开与新创建的数据库的另一个连接并运行测试脚本

– 获取当前连接的后端进程ID

SELECT pg_backend_pID();

– 打开一个linux控制台并运行ps -p并观看VIRT,RES和SHR

– 运行测试

选择MTDB_RunTests(‘tenant’,1);

观察:

>首次创建运行测试的连接时,

VIRT = 182MB,RES = 6240K,SHR = 4648K
>运行测试一次后,(耗时175秒)

VIRT = 1661MB RES = 1.5GB SHR = 55MB
>再次重新测试(耗时167秒)

VIRT = 1661MB RES = 1.5GB SHR = 55MB
>再次重新测试(耗时165秒)

VIRT = 1661MB RES = 1.5GB SHR = 55MB

当我们扩大表的数量时,内存使用量也会增加.

谁能帮忙解释一下这里发生了什么?
有没有办法控制Postgresql后端进程的内存使用?

谢谢.

塞缪尔

-- MTDB_destroycreate or replace function MTDB_destroy (schemanamePrefix varchar(100))returns int as $$declare   curs1 cursor(prefix varchar) is select schema_name from information_schema.schemata where schema_name like prefix || '%';   schemaname varchar(100);   count integer;begin   count := 0;   open curs1(schemanamePrefix);   loop      fetch curs1 into schemaname;      if not found then exit; end if;                 count := count + 1;      execute 'drop schema ' || schemaname || ' cascade;';   end loop;     close curs1;   return count;end $$language plpgsql;-- MTDB_Initializecreate or replace function MTDB_Initialize (schemanamePrefix varchar(100),numberOfSchemas integer,numberOftablesPerSchema integer,createVIEwForEachtable boolean)returns integer as $$declare      currentSchemaID integer;   currenttableID integer;   currentSchemaname varchar(100);   currenttablename varchar(100);   currentVIEwname varchar(100);   count integer;begin   -- clear   perform MTDB_Destroy(schemanamePrefix);   count := 0;   currentSchemaID := 1;   loop      currentSchemaname := schemanamePrefix || ltrim(currentSchemaID::varchar(10));      execute 'create schema ' || currentSchemaname;      currenttableID := 1;      loop         currenttablename := currentSchemaname || '.' || 'table' || ltrim(currenttableID::varchar(10));         execute 'create table ' || currenttablename || ' (f1 integer,f2 integer,f3 varchar(100),f4 varchar(100),f5 varchar(100),f6 varchar(100),f7 boolean,f8 boolean,f9 integer,f10 integer)';         if (createVIEwForEachtable = true) then            currentVIEwname := currentSchemaname || '.' || 'vIEw' || ltrim(currenttableID::varchar(10));            execute 'create vIEw ' || currentVIEwname || ' as ' ||                     'select t1.* from ' || currenttablename || ' t1 ' ||             ' inner join ' || currenttablename || ' t2 on (t1.f1 = t2.f1) ' ||             ' inner join ' || currenttablename || ' t3 on (t2.f2 = t3.f2) ' ||             ' inner join ' || currenttablename || ' t4 on (t3.f3 = t4.f3) ' ||             ' inner join ' || currenttablename || ' t5 on (t4.f4 = t5.f4) ' ||             ' inner join ' || currenttablename || ' t6 on (t5.f5 = t6.f5) ' ||             ' inner join ' || currenttablename || ' t7 on (t6.f6 = t7.f6) ' ||             ' inner join ' || currenttablename || ' t8 on (t7.f7 = t8.f7) ' ||             ' inner join ' || currenttablename || ' t9 on (t8.f8 = t9.f8) ' ||             ' inner join ' || currenttablename || ' t10 on (t9.f9 = t10.f9) ';                             end if;         currenttableID := currenttableID + 1;         count := count + 1;         if (currenttableID > numberOftablesPerSchema) then exit; end if;      end loop;         currentSchemaID := currentSchemaID + 1;      if (currentSchemaID > numberOfSchemas) then exit; end if;        end loop;   return count;END $$language plpgsql;-- MTDB_RunTestscreate or replace function MTDB_RunTests(schemanamePrefix varchar(100),rounds integer)returns integer as $$declare   curs1 cursor(prefix varchar) is select table_schema || '.' || table_name from information_schema.tables where table_schema like prefix || '%' and table_type = 'VIEW';   currentVIEwname varchar(100);   count integer;begin   count := 0;   loop      rounds := rounds - 1;      if (rounds < 0) then exit; end if;      open curs1(schemanamePrefix);      loop         fetch curs1 into currentVIEwname;         if not found then exit; end if;         execute 'select * from ' || currentVIEwname;         count := count + 1;      end loop;      close curs1;   end loop;   return count;  end $$language plpgsql;
这些连接在事务中是空闲还是空闲?听起来像未完成的事务正在持有内存,或者你可能有内存泄漏或其他什么. 总结

以上是内存溢出为你收集整理的PostgreSQL后端处理高内存使用问题全部内容,希望文章能够帮你解决PostgreSQL后端处理高内存使用问题所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://www.outofmemory.cn/sjk/1181837.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-02
下一篇 2022-06-02

发表评论

登录后才能评论

评论列表(0条)

保存