База на податоци за Messenger (дел 2): партиција „за профит“

Успешно ја дизајниравме структурата на нашата база на податоци PostgreSQL за складирање кореспонденција, помина една година, корисниците активно ја пополнуваат и сега содржи милиони записи, и... нешто почна да успорува.

База на податоци за Messenger (дел 2): партиција „за профит“
Факт е дека Како што расте големината на табелата, расте и „длабочината“ на индексите. - иако логаритамски. Но, со текот на времето ова го принудува серверот да ги извршува истите задачи за читање/запишување обработуваат многу пати повеќе страници со податоциотколку на почетокот.

Ова е местото каде што доаѓа до спасување пресекување.

Дозволете ми да забележам дека не зборуваме за шердинг, односно дистрибуција на податоци помеѓу различни бази на податоци или сервери. Бидејќи дури и поделбата на податоците на некои сервери, нема да се ослободите од проблемот со „отекување“ на индексите со текот на времето. Јасно е дека ако можете да си дозволите да ставате нов сервер во функција секој ден, тогаш вашите проблеми повеќе нема да лежат во рамнината на одредена база на податоци.

Ќе разгледаме не конкретни скрипти за имплементација на партиција „во хардвер“, туку самиот пристап - што и како треба да се „сече на парчиња“ и до што води таквата желба.

Концепт

Да ја дефинираме нашата цел уште еднаш: сакаме да се увериме дека денес, утре и за една година, количината на податоци што ги чита PostgreSQL за време на секоја операција за читање/запишување останува приближно ист.

За се хронолошки акумулирани податоци (пораки, документи, дневници, архиви, ...) природниот избор како клуч за партиција е датум/време на настанот. Во нашиот случај, таков настан е моментот на испраќање на пораката.

Имајте на ум дека корисниците речиси секогаш работи само со „најновите“. такви податоци - ги читаат најновите пораки, ги анализираат најновите дневници,... Не, се разбира, тие можат да се движат поназад во времето, но тоа го прават многу ретко.

Од овие ограничувања е јасно дека оптималното решение за порака би било „дневни“ делови - на крајот на краиштата, нашиот корисник скоро секогаш ќе чита што му дојде „денес“ или „вчера“.

Ако пишуваме и читаме речиси само во еден дел во текот на денот, тогаш и ова ни дава поефикасно користење на меморијата и дискот - бидејќи сите индекси на делови лесно се вклопуваат во RAM меморијата, за разлика од „големите и дебели“ низ табелата.

чекор по чекор

Во принцип, сè што е кажано погоре звучи како една континуирана добивка. И тоа е остварливо, но за ова ќе треба да се потрудиме - затоа што одлуката за поделба на еден од субјектите доведува до потреба да се „види“ поврзаното.

Порака, нејзините својства и проекции

Бидејќи решивме да ги исечеме пораките по датуми, има смисла да ги поделиме и ентитетите-својствата што зависат од нив (приложени датотеки, список на примачи) и исто така според датумот на пораката.

Бидејќи една од нашите типични задачи е прецизно гледање регистри на пораки (непрочитани, дојдовни, сите), исто така е логично да ги „ввлечеме“ во партиционирање по датуми на пораки.

База на податоци за Messenger (дел 2): партиција „за профит“

Го додаваме клучот за партиција (датум на порака) на сите табели: примачи, датотека, регистри. Не треба да го додавате во самата порака, туку користете го постојното DateTime.

Теми

Бидејќи има само една тема за неколку пораки, нема начин да ја „пресечете“ во ист модел, треба да се потпрете на нешто друго. Во нашиот случај тоа е идеално датум на првата порака во кореспонденцијата — односно моментот на создавање, всушност, на темата.

База на податоци за Messenger (дел 2): партиција „за профит“

Додајте го клучот за партиција (датум на тема) на сите табели: тема, учесник.

Но, сега имаме два проблеми одеднаш:

  • Во кој дел треба да барам пораки на темата?
  • Во кој дел да ја барам темата од пораката?

Можеме, се разбира, да продолжиме да бараме во сите делови, но ова ќе биде многу тажно и ќе ги негира сите наши добивки. Затоа, за да знаеме каде точно да бараме, ќе направиме логички врски/покажувачи до деловите:

  • ќе додадеме во пораката поле за датум на тема
  • да додадеме на темата поставен датум на порака оваа кореспонденција (може да биде посебна табела или низа датуми)

База на податоци за Messenger (дел 2): партиција „за профит“

Бидејќи ќе има неколку измени на списокот со датуми на пораки за секоја поединечна кореспонденција (на крајот на краиштата, скоро сите пораки паѓаат на 1-2 соседни денови), ќе се фокусирам на оваа опција.

Севкупно, структурата на нашата база на податоци ја зеде следнава форма, земајќи ја предвид поделбата:

Табели: RU, ако имате аверзија кон кирилицата во имињата на табелите/полињата, подобро е да не гледате

-- секции по дате сообщения
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
);

Заштедете прилично денар

Па, што ако не користиме класична опција за сечење врз основа на распределбата на вредностите на полињата (преку активирања и наследување или PARTITION BY), и „рачно“ на ниво на апликација, ќе забележите дека вредноста на клучот за партиција е веќе зачувана во името на самата табела.

Па ако сте така Дали сте многу загрижени за количината на складирани податоци?, тогаш можете да се ослободите од овие „дополнителни“ полиња и да адресирате одредени табели. Точно, сите селекции од неколку секции во овој случај ќе треба да се пренесат на страната на апликацијата.

Извор: www.habr.com

Додадете коментар