Мессенгер база података (2. део): партиционисање „за профит“

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

Мессенгер база података (2. део): партиционисање „за профит“
Чињеница је да је Како величина табеле расте, расте и „дубина“ индекса. - додуше логаритамски. Али током времена ово приморава сервер да обавља исте задатке читања/писања обради вишеструко више страница податаканего на почетку.

Ту долази у помоћ секција.

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

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

Koncept

Хајде да још једном дефинишемо наш циљ: желимо да будемо сигурни да данас, сутра и за годину дана количина података које ПостгреСКЛ чита током било које операције читања/писања остаје приближно иста.

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

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

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

Ако током дана пишемо и читамо скоро само у једном делу, онда нам и ово даје ефикасније коришћење меморије и диска - пошто се сви индекси секција лако уклапају у РАМ, за разлику од оних „великих и дебелих“ у табели.

корак по корак

Генерално, све што је горе речено звучи као један континуирани профит. И то је оствариво, али за ово ћемо морати да се потрудимо - јер одлука да се подели један од ентитета доводи до потребе да се „пиле” придружени.

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

Пошто смо одлучили да исечемо поруке по датумима, има смисла поделити и ентитете-својства која зависе од њих (приложене датотеке, листа прималаца) и такође по датуму поруке.

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

Мессенгер база података (2. део): партиционисање „за профит“

Додајемо кључ за партиционисање (датум поруке) у све табеле: примаоце, фајл, регистре. Не морате га додати самој поруци, већ користите постојећи ДатеТиме.

Теме

Пошто постоји само једна тема за неколико порука, не постоји начин да се она „исече“ у истом моделу; морате се ослонити на нешто друго. У нашем случају је идеално датум прве поруке у преписци — односно тренутак стварања, заправо, теме.

Мессенгер база података (2. део): партиционисање „за профит“

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

Али сада имамо два проблема одједном:

  • У ком делу треба да потражим поруке на ту тему?
  • У ком делу треба да потражим тему из поруке?

Можемо, наравно, да наставимо да тражимо у свим одељцима, али ово ће бити веома тужно и поништиће све наше добитке. Стога, да бисмо знали где тачно да тражимо, направићемо логичке везе/показиваче на секције:

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

Мессенгер база података (2. део): партиционисање „за профит“

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

Укупно, структура наше базе података је имала следећи облик, узимајући у обзир партиционисање:

Табеле: РУ, ако имате одбојност према ћирилици у називима табела/поља, боље је да не гледате

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

Уштедите прилично пени

Па, шта ако користимо не опција класичне секције на основу дистрибуције вредности поља (преко окидача и наслеђивања или ПАРТИТИОН БИ), и „ручно“ на нивоу апликације, приметићете да је вредност партиционог кључа већ ускладиштена у имену саме табеле.

Па ако јеси Да ли сте веома забринути због количине похрањених података?, онда се можете ослободити ових „додатних“ поља и адресирати одређене табеле. Истина, сви избори из неколико секција у овом случају ће морати да се пренесу на страну апликације.

Извор: ввв.хабр.цом

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