PostgreSQL kullanarak çok bantlı bir veritabanı uygulamak için değerlendirmeler yapıyoruz, Şu anda tek veritabanı-çoklu şema modelinde bazı testler yapıyoruz (tüm kiracılar aynı veritabanı nesnelerine sahiptir) Aynı veritabanı içinde kendi şeması altında). Uygulama, tüm kiracılar/şemalar arasında paylaşılacak bir bağlantı havuzu sağlayacaktır.PostgreSQL backend işlemi yüksek bellek kullanımı sorunu
örn. Veritabanında 500 kiracı/şema varsa ve her kiracının 200 tablo/görüş alanı varsa, toplam tablo/görüntüleme sayısı 500 * 200 = 100.000 olacaktır.
Bağlantı havuzu tüm kiracılar tarafından kullanılacağından, her bağlantı sonunda tüm tablolara/görünümlere çarpacaktır.
Testlerimizde, bağlantı daha fazla görünüme ulaştığında, arka uç işleminin bellek kullanımının oldukça hızlı arttığını ve çoğunun özel bellek olduğunu gördük. Bağlantı kapanana kadar bu hafıza tutulacaktır.
Bir arka uç işlemin 30GB daha fazla bellek kullandığını ve nihayetinde yetersiz bellek hatası aldığını bir test vakamız var. sorunu anlamak yardımcı olmak için
, ben basitleştirilmiş test durumları oluşturmak için kod yazdı - MTDB_destroy: kiracı şemaları temizlemek için kullanılan - MTDB_Initialize: Bir DB multitenant oluşturmak için kullanılan - MTDB_RunTests: basitleştirilmiş test durumda, temelde bütün seçim Kiracı tek tek görüyor. Yaptığım
testler 5.4
Ben (tek şey temiz bir çevre, ben yeniden oluşturulur veritabanı küme vardır ve varsayılan olarak çoğunluk yapılandırmaları terk emin olmak için CentOS üzerinde PostgreSQL 9.0.3 oldu Ben değiştirmeye VAR MTDB_destroy sayıda nesne düşmesi gerekiyor çünkü "max_locks_per_transaction" artırmaktır) Bu benim sorunu yeniden oluşturmak için ne olduğunu
:. yeni bir veritabanı oluşturmak
-
; Başlat
-
db oluşturulan yeni bağlanmak
- ekli kodu kullanarak üç işlevler oluşturmak ve ilklendir geçiri çalıştırmak
yeni oluşturulan db'ye başka bir bağlantı açmak ve test komut dosyalarını çalıştırmak
-) (akım bağlantısı için
SEÇ pg_backend_pid arka uç işlem kimliği almak;
- Bir Linux konsolu açın ve ps -p çalıştırın ve VIRT, RES ve SHR
izle - çalıştırmak testler
seçme MTDB_RunTests ('kiracı', 1);
(gerçek 'kiracı', 100, 100) MTDB_Initialize seç - 10
- vakum analiz emin değil ben sadece
vakum analiz çalıştırmak, burada yararlıdır;
- check tablolar/görünümler INFORMATION_SCHEMA gelenseçme TABLE_SCHEMA TABLE_TYPE, saymak (*) oluşturuldu.table_schema'ın table_schema, table_schema, table_type;
Gözlemler:
testleri çalıştırmak için bağlantı ilk oluşturulduğu,
VIRT = 182MB, RES = 6240K SHR = 4648K
testler sonrasında bir kere, (175 saniye sürmüştür)
VIRT = 1661MB RES = 1.5GB SHR = 55MB
yeniden çalıştırmak tekrar test (167 saniye sürmüştür)
yeniden çalıştırmak daha testi
(165 saniye sürmüştür) VIRT = 1661MB RES = 1.5 GB SHR = 55MB biz tablo sayısını büyütmek olarak VIRT = 1661MB RES = 1.5GB SHR = 55MB
, hafıza kullanımları da testlerde kadar gitmek.
Burada neler olduğunu açıklayan herkes yardımcı olabilir mi? PostgreSQL backend işleminin bellek kullanımını kontrol etmemizin bir yolu var mı?
Teşekkürler.
Samuel
-- MTDB_destroy
create 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_Initialize
create 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_RunTests
create 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;
Am doğru olduğunu bellek kullanımı sadece sürece açık bir bağlantı tutmak gibi artar? Bundan kaçınmak için şemaları değiştirdiğiniz her n 'bağlantıyı kapatıp tekrar açamaz mıydınız? –
Evet, bağlantıyı kapatırsak, işlem için ayrılan bellek geri döndürür. Ancak, bu da ideal değil. Bağlantı havuzu fikri, db sunucusuna eşzamanlı bağlantıların sayısını azaltmak ve bağlantı/bağlantı maliyetini kaldırmaktır (her istek için bunu yapmak zorunda kalırsak kolayca hatırlanabilir) – Samuel