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) болон хэрэглээний түвшинд "гараар" үндэслэн хуваах түлхүүрийн утгыг хүснэгтийн нэр дээр аль хэдийн хадгалсан болохыг анзаарах болно.

Тиймээс хэрэв та тийм бол Хадгалагдсан өгөгдлийн хэмжээнээс та маш их санаа зовж байна уу?, дараа нь та эдгээр "нэмэлт" талбаруудаас салж, тодорхой хүснэгтүүдийг хаяглаж болно. Үнэн бол энэ тохиолдолд хэд хэдэн хэсгээс бүх сонголтыг програмын тал руу шилжүүлэх шаардлагатай болно.

Эх сурвалж: www.habr.com

сэтгэгдэл нэмэх