---
title: "Ręczne partycjonowanie w PostgreSQL"
url: https://michalasobczak.pl/pl/posts/postgresql-manual-partitioning.html
author: "Michał Sobczak"
description: "Zastanawiałeś się kiedyś, ile tabel możemy utworzyć i używać w serwerze baz danych PostgreSQL? Czy nazywać je partycjami, czy shardami? Dlaczego nie użyć wbudowanego „automatycznego” partycjonowania? Partycje czy shardy? Najpierw zdefiniujmy różnicę między partycjami a shardami."
published: 2024-09-21T16:57:28.000Z
updated: 2024-09-21T16:57:28.000Z
language: pl
categories: ["Technology"]
tags: ["PostgreSQL"]
license: CC BY-NC-ND 4.0 (https://creativecommons.org/licenses/by-nc-nd/4.0/)
---
# Ręczne partycjonowanie w PostgreSQL

> Zastanawiałeś się kiedyś, ile tabel możemy utworzyć i używać w serwerze baz danych PostgreSQL? Czy nazywać je partycjami, czy shardami? Dlaczego nie użyć wbudowanego „automatycznego” partycjonowania?

## Partycje czy shardy?

Najpierw zdefiniujmy różnicę między partycjami a shardami. Partycje znajdują się na tym samym serwerze, natomiast shardy mogą być rozłożone na różne maszyny. Możemy użyć dziedziczenia lub nowszego, „automatycznego” partycjonowania. Oba te rozwiązania prowadzą jednak do ścisłego powiązania z RDBMS PostgreSQL, czego w niektórych sytuacjach chcielibyśmy uniknąć. Wyobraź sobie perspektywę migracji naszych schematów do innego RDBMS, takiego jak Microsoft SQL Server. Niekorzystanie z żadnej składni i konfiguracji specyficznej dla dostawcy byłoby wtedy korzystne.

## Partycje niezależne od dostawcy

Zamiast tego możemy więc po prostu spróbować ręcznie utworzyć tabele pełniące rolę partycji:

```sql
sudo apt install postgresql -y
sudo -u postgres -i
psql
CREATE DATABASE paritions
exit
```

Następnie, po zainstalowaniu PostgreSQL i utworzeniu nowej bazy danych:

```text
for i in `seq 1 10000`; 
do 
  echo $i;
  psql -c "create table demo_$i (id int, val int);" partitions; 
done
```

W ten sposób utworzyliśmy 10 000 tabel, używając wyłącznie ogólnej składni SQL, która jest w 100% kompatybilna ze wszystkimi innymi RDBMS. Co ważniejsze, nie zależymy od konfiguracji pamięci współdzielonej ani od ograniczeń wynikających z dołączenia zbyt wielu partycji do tabeli głównej.

## Ile zwykłych partycji mogę mieć?

W przypadku PostgreSQL (zwykłe partycje), jeśli dołączymy zbyt wiele tabel, łatwo możemy zacząć odczuwać to negatywnie pod względem **wydajności i zużycia pamięci**. Jeśli więc chcesz używać „automatycznego” partycjonowania PostgreSQL, pamiętaj, by nie dołączać zbyt wielu tabel. Ile to zbyt wiele? Zacząłem to zauważać już po dołączeniu 100 – 200 tabel, co w małych/średnich wdrożeniach powinno być naszą górną granicą.

## Jak duże mogą być moje dane?

Jeśli chodzi o to, jak duży może być pojedynczy węzeł PostgreSQL, powiedziałbym, że 5 – 10 TB danych z tabelami osiągającymi (wraz z toastami) 2 TB to dość normalna sytuacja i zwykły sprzęt sobie z tym poradzi. Jeśli masz na serwerze 512 GB RAM, bufor i cache wystarczą do pracy na tak ogromnych tabelach.

## Ile tabel mogę utworzyć w pojedynczym węźle?

Jak wspomniałem wcześniej, ogranicza cię przestrzeń dyskowa, pamięć i CPU – jak zawsze. Powinieneś jednak monitorować także liczbę **i-węzłów (inodes)** oraz liczbę **deskryptorów plików** w systemie, ponieważ te osobne tabele mogą trafiać do różnych plików, a ma to jeszcze większe znaczenie, jeśli w rekordach umieszczamy długie dane, które trafiają do **toastów**. Używanie zwykłych tabel jako partycji to jednak najbardziej **zdenormalizowany** sposób osiągnięcia celu, jakim jest fizyczny podział danych.

**Mogę powiedzieć, że 50 000 tabel w pojedynczym węźle to nic złego, nawet w małym/średnim systemie.**

Ale jaki jest faktyczny limit? Myślę, że jedyny praktyczny limit wynika z **ograniczeń sprzętu i systemu operacyjnego**. W kontenerze LXC z Ubuntu 22, z dyskiem 8GB, 1 vCPU i 512 MB pamięci mamy dostępnych 524 tys. i-węzłów. Po dodaniu 50 tys. tabel widzimy, że liczba i-węzłów wzrosła do 77126, co stanowi 15% całej dostępnej puli.

```text
postgres@z10-test:~$ df -i
Filesystem                        Inodes IUsed   IFree IUse% Mounted on
/dev/mapper/pve-vm--131--disk--0  524288 77126  447162   15% /
none                             4070043    25 4070018    1% /dev
tmpfs                            4070043     2 4070041    1% /dev/shm
tmpfs                             819200   149  819051    1% /run
tmpfs                            4070043     2 4070041    1% /run/lock
tmpfs                             814008    11  813997    1% /run/user/110
```

Myślę, że przynajmniej z perspektywy i-węzłów jesteśmy po bezpiecznej stronie, nawet przy 50 tys. tabel.

## Jak zatem zaprojektować architekturę danych?

Wyobraźmy sobie teraz rzeczywisty scenariusz systemu obsługującego milion klientów. Przy takiej liczbie zalecałbym posiadanie wielu węzłów w różnych lokalizacjach, aby zmniejszyć opóźnienia (w przypadku usług globalnych). Architektura aplikacji również musiałaby być rozproszona. Używalibyśmy więc zarówno partycjonowania w obrębie jednego węzła, jak i shardingu „per se”. Z drugiej strony możemy pozostać przy pojedynczym shardzie ze wszystkimi klientami w jednym węźle, a właściwą pracę wykonywać w węzłach Cassandry, a nie w RDBMS….
