پایگاه داده مسنجر (قسمت 2): پارتیشن بندی "برای سود"

ما با موفقیت ساختار پایگاه داده PostgreSQL خود را برای ذخیره مکاتبات طراحی کردیم، یک سال گذشته است، کاربران به طور فعال آن را پر می کنند، و اکنون میلیون ها رکورد، و ... چیزی شروع به کند کردن همه چیز کرد.

پایگاه داده مسنجر (قسمت 2): پارتیشن بندی "برای سود"
واقعیت این است که با رشد حجم جدول، "عمق" شاخص ها نیز رشد می کند - هر چند لگاریتمی. اما با گذشت زمان سرور را مجبور می‌کند تا همان وظایف خواندن/نوشتن را انجام دهد صفحات داده چندین برابر بیشتر را پردازش کنیدنسبت به ابتدا

اینجاست که به نجات می رسد بخش بندی.

توجه داشته باشم که این مربوط به اشتراک گذاری نیست، یعنی توزیع داده ها بین پایگاه های داده یا سرورهای مختلف. زیرا حتی تقسیم داده ها بر برخی از سرورها، با گذشت زمان از مشکل "تورم" ایندکس ها خلاص نخواهید شد. واضح است که اگر بتوانید هر روز یک سرور جدید را به کار بگیرید، دیگر مشکلات شما در یک پایگاه داده خاص قرار نخواهد گرفت.

ما اسکریپت های خاصی را برای اجرای پارتیشن بندی "در سخت افزار" در نظر نمی گیریم، بلکه خود رویکرد را در نظر خواهیم گرفت - چه چیزی و چگونه باید "به برش بریده شود" و چنین تمایلی به چه چیزی منجر می شود.

مفهوم

یک بار دیگر، هدف خود را مشخص می کنیم: می خواهیم مطمئن شویم که امروز، فردا و یک سال بعد، مقدار داده های خوانده شده توسط PostgreSQL برای هر عملیات خواندن/نوشتن تقریباً یکسان باقی می ماند.

برای هرچی داده های انباشته زمانی (پیام ها، اسناد، لاگ ها، بایگانی ها، ...) انتخاب طبیعی برای کلید پارتیشن است تاریخ/زمان رویداد. در مورد ما، این رویداد است لحظه ارسال پیام.

توجه داشته باشید که کاربران تقریبا همیشه فقط با جدیدترین ها کار کنید چنین داده‌هایی - آنها آخرین پیام‌ها را می‌خوانند، آخرین گزارش‌ها را تجزیه و تحلیل می‌کنند، ... نه، البته، آنها می‌توانند بیشتر در زمان اسکرول کنند، فقط به ندرت این کار را انجام می‌دهند.

از این محدودیت ها مشخص می شود که راه حل بهینه برای پیام ها خواهد بود بخش های "روزانه" - از این گذشته ، تقریباً همیشه کاربر ما آنچه را که "امروز" یا "دیروز" برای او آمده است می خواند.

اگر در طول روز فقط در یک بخش بنویسیم و بخوانیم، این به ما هم می‌دهد استفاده کارآمدتر از حافظه و دیسک - از آنجایی که همه شاخص های بخش به راحتی در حافظه RAM قرار می گیرند، برخلاف موارد "بزرگ و چاق" در سراسر جدول.

گام به گام

به طور کلی، همه موارد فوق مانند یک سود بزرگ به نظر می رسد. و قابل دستیابی است، اما برای این ما باید سخت کار کنیم - زیرا تصمیم به پارتیشن بندی یکی از موجودیت ها منجر به نیاز به "اره" و مرتبط می شود.

پیام، ویژگی ها و پیش بینی های آن

از آنجایی که تصمیم گرفتیم پیام ها را بر اساس تاریخ برش دهیم، منطقی است که ویژگی های موجودیت وابسته به آنها (فایل های پیوست، لیست گیرندگان) و همچنین بر اساس تاریخ ارسال.

از آنجایی که یکی از کارهای معمول ما فقط مشاهده رجیسترهای پیام است (خوانده نشده، ورودی، همه)، منطقی است که آنها را به بخش بندی بر اساس تاریخ پیام بکشیم.

پایگاه داده مسنجر (قسمت 2): پارتیشن بندی "برای سود"

ما کلید پارتیشن (تاریخ پیام) را به همه جداول اضافه می کنیم: گیرندگان، فایل ها، رجیستری ها. شما نمی توانید به خود پیام اضافه کنید، اما از DateTime موجود استفاده کنید.

موضوعات

از آنجایی که موضوع یکی برای چندین پیام است، نمی توان آن را در یک مدل "برش" کرد، باید به چیز دیگری تکیه کرد. ایده آل برای مورد ما تاریخ اولین پیام در مکاتبات - یعنی لحظه خلقت، در واقع موضوع.

پایگاه داده مسنجر (قسمت 2): پارتیشن بندی "برای سود"

یک کلید پارتیشن (تاریخ موضوع) به همه جداول اضافه کنید: موضوع، عضو.

اما اکنون دو مشکل داریم:

  • در کدام بخش پیام های مربوط به موضوع را جستجو کنیم؟
  • در کدام بخش موضوع پیام را جستجو کنیم؟

البته می‌توانید در همه بخش‌ها به جستجو ادامه دهید، اما بسیار غم انگیز خواهد بود و همه بردهای ما را نفی می‌کند. بنابراین، برای اینکه بدانیم دقیقاً به کجا نگاه کنیم، پیوندها / اشاره گرهای منطقی به بخش ها ایجاد می کنیم:

  • به پیام اضافه کنید فیلد تاریخ موضوع
  • به موضوع اضافه کنید تاریخ پیام تنظیم شد این مکاتبات (می توانید از یک جدول جداگانه استفاده کنید، یا می توانید از آرایه ای از تاریخ ها استفاده کنید)

پایگاه داده مسنجر (قسمت 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

اضافه کردن نظر