Messenger adatbázis (2. rész): particionálás „profitért”

Sikeresen megterveztük PostgreSQL adatbázisunk felépítését a levelezés tárolására, eltelt egy év, a felhasználók aktívan töltik, és most már tartalmazza több millió rekordot, és... valami lassulni kezdett.

Messenger adatbázis (2. rész): particionálás „profitért”
Tény az, hogy a A táblázat méretének növekedésével az indexek „mélysége” is nő. - bár logaritmikusan. De idővel ez arra kényszeríti a szervert, hogy ugyanazokat az olvasási/írási feladatokat hajtsa végre sokszor több oldal adatot dolgoz felmint az elején.

Itt jön a segítség szakaszolás.

Hadd jegyezzem meg, hogy nem shardingról, vagyis az adatok különböző adatbázisok vagy szerverek közötti elosztásáról beszélünk. Mert még az adatokat felosztva is néhány szerverek, akkor nem fog megszabadulni az indexek idővel „duzzadó” problémájától. Nyilvánvaló, hogy ha megengedheti magának, hogy minden nap üzembe helyezzen egy új szervert, akkor a problémák már egyáltalán nem egy adott adatbázis síkjában rejlenek.

Nem specifikus szkripteket fogunk figyelembe venni a particionálás „hardverben” megvalósításához, hanem magát a megközelítést - mit és hogyan kell „szeletekre vágni”, és mire vezet egy ilyen vágy.

Koncepció

Határozzuk meg még egyszer a célunkat: szeretnénk elérni, hogy ma, holnap és egy év múlva a PostgreSQL által bármilyen olvasási/írási művelet során beolvasott adatok mennyisége megközelítőleg változatlan maradjon.

Bármilyen kronológiailag felhalmozott adatok (üzenetek, dokumentumok, naplók, archívumok, ...) a természetes választás particionáló kulcsként esemény dátuma/időpontja. Esetünkben egy ilyen esemény az az üzenet elküldésének pillanata.

Vegye figyelembe, hogy a felhasználók szinte mindig csak a „legújabbakkal” dolgozzon ilyen adatok - elolvassák a legfrissebb üzeneteket, elemzik a legfrissebb naplókat,... Nem, természetesen tovább görgethetnek az időben, de ezt nagyon ritkán teszik meg.

Ezekből a korlátokból egyértelmű, hogy az optimális üzenetmegoldás lenne "napi" szakaszok - elvégre a felhasználónk szinte mindig elolvassa, mi jutott neki „ma” vagy „tegnap”.

Ha napközben szinte csak egy részben írunk és olvasunk, akkor ez is megadja nekünk a memória és a lemez hatékonyabb kihasználása - mivel minden szekcióindex könnyen belefér a RAM-ba, ellentétben a táblázatban szereplő „nagy és kövér”-ekkel.

lépésről lépésre

Általánosságban elmondható, hogy a fent elmondottak egy folyamatos nyereségnek tűnnek. És ez elérhető, de ehhez keményen kell próbálkoznunk - mert az egyik entitás felosztására vonatkozó döntés ahhoz vezet, hogy „látni” kell a társított entitást.

Üzenet, tulajdonságai és vetületei

Mivel úgy döntöttünk, hogy dátum szerint vágjuk le az üzeneteket, célszerű a tőlük függő entitásokat-tulajdonságokat is felosztani (csatolt fájlok, címzettek listája), ill. az üzenet dátuma szerint is.

Mivel az egyik tipikus feladatunk az üzenetregiszterek (olvasatlan, bejövő, összes) precíz megtekintése, logikus az is, hogy ezeket az üzenetdátumok szerinti particionálásba „berajzoljuk”.

Messenger adatbázis (2. rész): particionálás „profitért”

Minden táblához hozzáadjuk a particionáló kulcsot (üzenet dátuma): címzettek, fájl, nyilvántartások. Nem kell hozzá az üzenethez, hanem a meglévő DateTime-t kell használnia.

Темы

Mivel több üzenethez csak egy téma tartozik, azt nem lehet ugyanabba a modellbe „vágni”, másra kell hagyatkozni. A mi esetünkben ideális az első levelező üzenet dátuma - vagyis a teremtés pillanata, tulajdonképpen a téma.

Messenger adatbázis (2. rész): particionálás „profitért”

Adja hozzá a particionáló kulcsot (téma dátuma) az összes táblához: téma, résztvevő.

De most egyszerre két problémánk van:

  • Melyik rovatban keressem a témával kapcsolatos üzeneteket?
  • Melyik részben keressem a témát az üzenetből?

Természetesen folytathatjuk a keresést az összes szekcióban, de ez nagyon szomorú lesz, és érvényteleníteni fogja az összes nyereményünket. Ezért annak érdekében, hogy pontosan tudjuk, hol kell keresni, logikai hivatkozásokat/mutatókat készítünk a szakaszokhoz:

  • hozzáadjuk az üzenetben téma dátuma mezőben
  • egészítsük ki a témát üzenet dátuma beállítva ez a levelezés (lehet külön táblázat vagy dátumtömb)

Messenger adatbázis (2. rész): particionálás „profitért”

Mivel az egyes levelezések üzenetdátumainak listája kevés módosulni fog (elvégre szinte minden üzenet 1-2 szomszédos napra esik), erre a lehetőségre fogok összpontosítani.

Összességében adatbázisunk felépítése a következő formát öltötte, figyelembe véve a particionálást:

Táblázatok: RU, ha idegenkedsz a cirill ábécétől a táblázatok/mezők nevében, jobb, ha nem nézed

-- секции по дате сообщения
CREATE TABLE "Сообщение_YYYYMMDD"(
  "Сообщение"
    uuid
      PRIMARY KEY
, "Тема"
    uuid
, "ДатаТемы"
    date
, "Автор"
    uuid
, "ДатаВремя" -- используем как дату
    timestamp
, "Текст"
    text
);

CREATE TABLE "Адресат_YYYYMMDD"(
  "ДатаСообщения"
    date
, "Сообщение"
    uuid
, "Персона"
    uuid
, PRIMARY KEY("Сообщение", "Персона")
);

CREATE TABLE "Файл_YYYYMMDD"(
  "ДатаСообщения"
    date
, "Файл"
    uuid
      PRIMARY KEY
, "Сообщение"
    uuid
, "BLOB"
    uuid
, "Имя"
    text
);

CREATE TABLE "РеестрСообщений_YYYYMMDD"(
  "ДатаСообщения"
    date
, "Владелец"
    uuid
, "ТипРеестра"
    smallint
, "ДатаВремя"
    timestamp
, "Сообщение"
    uuid
, PRIMARY KEY("Владелец", "ТипРеестра", "Сообщение")
);
CREATE INDEX ON "РеестрСообщений_YYYYMMDD"("Владелец", "ТипРеестра", "ДатаВремя" DESC);

-- секции по дате темы
CREATE TABLE "Тема_YYYYMMDD"(
  "ДатаТемы"
    date
, "Тема"
    uuid
      PRIMARY KEY
, "Документ"
    uuid
, "Название"
    text
);

CREATE TABLE "УчастникТемы_YYYYMMDD"(
  "ДатаТемы"
    date
, "Тема"
    uuid
, "Персона"
    uuid
, PRIMARY KEY("Тема", "Персона")
);

CREATE TABLE "ДатыСообщенийТемы_YYYYMMDD"(
  "ДатаТемы"
    date
, "Тема"
    uuid
      PRIMARY KEY
, "Дата"
    date
);

Takarítson meg egy szép fillért

Nos, mi van, ha nem használjuk klasszikus szakaszolási lehetőség a mezőértékek eloszlása ​​alapján (triggereken és öröklődésen vagy PARTITION BY-n keresztül), valamint „manuálisan” az alkalmazás szintjén észreveheti, hogy a particionáló kulcs értéke már magában a tábla nevében is el van tárolva.

Tehát ha így van Nagyon aggódik a tárolt adatok mennyisége miatt?, akkor megszabadulhat ezektől az „extra” mezőktől, és megcímezheti az adott táblákat. Igaz, ebben az esetben több szekció összes kijelölését át kell vinni az alkalmazás oldalára.

Forrás: will.com

Hozzászólás