Messenger տվյալների բազա (մաս 2). բաժանում «շահույթի համար»

Մենք հաջողությամբ նախագծել ենք մեր PostgreSQL տվյալների բազայի կառուցվածքը նամակագրությունը պահելու համար, անցել է մեկ տարի, օգտվողներն ակտիվորեն լրացնում են այն, և այժմ այն ​​պարունակում է միլիոնավոր գրառումներ, և... ինչ-որ բան սկսեց դանդաղել։

Messenger տվյալների բազա (մաս 2). բաժանում «շահույթի համար»
Փաստն այն է, որ Քանի որ սեղանի չափը մեծանում է, աճում է նաև ինդեքսների «խորությունը»: - թեկուզ լոգարիթմական: Բայց ժամանակի ընթացքում դա ստիպում է սերվերին կատարել նույն ընթերցման/գրելու առաջադրանքները մշակել բազմաթիվ անգամ ավելի շատ տվյալների էջերքան սկզբում։

Այստեղ է, որ օգնության է հասնում հատվածավորում.

Նշեմ, որ խոսքը Sharding-ի, այսինքն՝ տվյալների տարբեր բազաների կամ սերվերների միջև տվյալների բաշխման մասին չէ։ Քանի որ նույնիսկ տվյալները բաժանելով մոտ սերվերներ, դուք չեք ազատվի ժամանակի ընթացքում ինդեքսների «ուռչելու» խնդրից: Հասկանալի է, որ եթե դուք կարող եք ձեզ թույլ տալ ամեն օր գործարկել նոր սերվեր, ապա ձեր խնդիրներն այլևս չեն ընկնի կոնկրետ տվյալների բազայի հարթությունում:

Մենք կքննարկենք ոչ թե հատուկ սցենարներ «ապարատային» բաժանման իրականացման համար, այլ մոտեցումն ինքնին.

Հայեցակարգ

Եկեք ևս մեկ անգամ սահմանենք մեր նպատակը. մենք ուզում ենք համոզվել, որ այսօր, վաղը և մեկ տարի հետո 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-ի միջոցով) և «ձեռքով» հավելվածի մակարդակում, դուք նկատում եք, որ բաժանման ստեղնի արժեքն արդեն պահված է հենց աղյուսակի անունով:

Այսպիսով, եթե դուք այդպիսին եք Ձեզ շա՞տ անհանգստացնում է պահվող տվյալների քանակը:, ապա դուք կարող եք ազատվել այս «լրացուցիչ» դաշտերից և հասցեագրել կոնկրետ աղյուսակներ: Ճիշտ է, այս դեպքում մի քանի բաժիններից բոլոր ընտրությունները պետք է տեղափոխվեն դիմումի կողմ:

Source: www.habr.com

Добавить комментарий