Vahid
Vahid
خواندن ۶ دقیقه·۲ سال پیش

آشنایی عمیق تر با Timescale DB

مقدمه

اگر با داده‌های بر اساس زمان سر و کار داشته باشید، می‌دونید که پایگاه‌داده‌های RDBMS موقع جستجو زیاد عملکرد خوبی ندارن و می‌تونن کُند باشند(مخصوصا توی حجم دیتای بالا). برای حل این مشکل، پایگاه‌داده‌های بر اساس زمان(time series database) به وجود اومدند. این پایگاه‌داده‌ها نحوه ذخیره‌سازیشون متفاوته و به جای اینکه دیتا رو به صورت سطری ذخیره کنند، به صورت ستونی ذخیره می‌کنند. اگر هم بخوایم چند تا نمونه از این پایگاه‌داده‌ها بگیم، می‌تونیم به click house، InfluxDB، QuestDB و timescale db اشاره کنیم. از بین این موارد که ما به timescale db علاقه مندیم. دلیلش هم اینه که، این پایگاه داده اومده از postgres استفاده کرده! اینکه چطوری یک پایگاه داده RDBMS می‌تونه همچین چیزی رو پشتیبانی کنه سوالی بود که منتج به این مطلب شد.

https://thenewstack.io/time-series-data-care/
https://thenewstack.io/time-series-data-care/

TimescaleDB

شاید اگر کسی اسم TimescaleDB رو بشنوه با خودش فکر کنه که داره اسم یک پایگاه داده رو می‌شنوه(منظور یک چیزی مثل mysql یا mongodb)، ولی در واقعیت TimescaleDB یک افزونه(extension) برای postgres هستش و روی این پایگاه داده نصب میشه همین! اتفاقا TimescaleDB خیلی با این موضوع هم حال می‌کنه و میگه که من از تجربه ۳۰ سال توسعه پستگرس استفاده می‌کنم پس به من اعتماد کنید(آیا واقعا میشه بهش اعتماد کرد؟ این موضوع یک بحث دیگه‌ست). اما خب پستگرس چطوری تونسته این زیرساخت رو برای TimescaleDB فراهم کنه؟ آیا بقیه RDBMS ها نمی‌تونن؟ اینکه آیا بقیه RDBMS ها می‌تونن یا نه؟ خودم اطلاع دقیقی ازش ندارم(یک سرچ ریزی که زدم برای معروف‌ها چیزی ندیدم. اگر کسی می‌دونه خوشحال میشم دانشش رو با ما هم توی کامنت‌ها به اشتراک بزاره). منطقی هم هستش که مورد به مورد بررسی بشه ولی در لحظه زیاد برای ما مهم نیست چون می‌خوایم درمورد TimescaleDB حرف بزنیم که اونم داره از پستگرس استفاده می‌کنه. پس بریم ببینیم که پستگرس برای این موضوع چه کرده.

Hypertables

هایپرتیبل یک نوع از جدول‌هایی که پستگرس تو خودش داره و به خاطر بعضی ویژگی‌هایی که دارن کار رو برای مدیریت داده‌های زمانی رو آسون می‌کنن. تازه هر کاری که با یک جدول عادی توی پستگرس انجام میدیم رو توی هایپرتیبل‌ها هم می‌تونیم انجام بدیم. خب فهمیدیم کلمه کلیدی ماجرا hypertable هستش ولی هنوز متوجه نشدیم که این هایپرتیبل ها چی دارن که کار کردن با داده‌های زمانی رو برای ما آسون می‌کنه؟ به طور خاص یک ویژگی اساسیه که این موضوع رو راحت می‌کنه و اون چیزی نیست جر Time partitioning. البته یک ویژگی دیگه هم داره به اسم Space partitioning ولی خب نکته اساسی ماجرا همون تقسیم بندی براساس زمانه.

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

CREATE HYPERTABLE table_name( column1 datatype, column2 TIMESTAMPTZ, ... PRIMARY KEY( one or more columns ) );

برای ساخت hypertable ما باید اول یک جدول عادی بسازیم:

CREATE TABLE table_name( column1 datatype, column2 TIMESTAMPTZ, ..... columnN datatype, PRIMARY KEY( one or more columns ) );

بعد بیایم این جدول رو به hypertable تبدیلش کنیم. نکته اساسی هم اینه که جدولی که می‌خوایم این اتفاق براش بیوفته، حتما یک فیلد بر اساس زمان داشته باشه(توی مثال بالا column2). این تبدیل هم به این شکل انجام میشه:

SELECT create_hypertable('table_name', 'time_column_name');

این تبدیل حتی برای جدول‌هایی که از قبل دیتا دارن هم امکان پذیره(باید موقع تبدیل متغیر migrate_data رو بفرستیم). میزان اطلاعات جدول هم هر چی بیشتر باشه، مدت زمان این تبدیل بیشتر میشه.

ساختار داخلی hypertable

پس فهمیدیم که hypertable‌ها بر اساس زمان(time) و فضا(space) کار می‌کنه. این نکته وقتی جالب‌تر میشه که بدونیم:

موقعی که ما یک hypertable می‌سازیم، به صورت خودکار بر اساس زمان تقسیم‌بندی میشه(به صورت دلخواه میشه براساس space هم این کار رو کرد). در واقع هر hypertable یک از سری جدول‌های کوچک‌تر به اسم chunk تشکیل شده. این بخش‌های کوچیک یک بازه زمانی رو دربرمی‌گیرن که فقط دیتا‌های اون بازه زمانی رو تو خودشون دارن. اگر هم hypertable براساس فضا(space) تقسیم‌بندی شده باشه، هر chunk یک بخشی از مقادیر اون فضا رو خواهد داشت. شکل پایین رو یک نگاه بندازین:
https://docs.timescale.com/timescaledb/latest/how-to-guides/hypertables/about-hypertables/
https://docs.timescale.com/timescaledb/latest/how-to-guides/hypertables/about-hypertables/

سوال بعدی که ممکنه پیش بیاد اینه که ایا سایز این بخش‌ها(chunkها) قابل تنظیم هستش یا نه؟ که جواب کوتاه بله ست. اما تعیین سایز این بخش‌ها نقش مهمی رو توی سرعت کوئری‌های ما داره. طبیعتا اینکه بخش‌های ما یک هفته ای باشه یا یک روزه خیلی با هم فرق داره. برای این کار متغیر chunk_time_interval به ما کمک می‌کنه. طبق مستندات TimescaleDB مقدار توصیه شده برای این متغیر عبارت است از: ۲۵٪ از حافظه اصلی برای یک بخش(chunk). یعنی ۲۵ درصد از حافظه اصلی توی بشه یک بخش(chunk) دیتا یا به عبارت دیگه یک بخش دیتا ۲۵٪ حافظه اصلی رو پر کنه. مثلا اگر به طور تقریبی روزانه ۲ گیگ دیتا رو خواهید داشت و حافظه اصلی‌تون هم ۶۴ گیگه، هر بخش(chunk) رو می‌تونیم ۱ هفته بزاریم یا اگر به صورت روزانه ۱۰ گیگ دیتا داشته باشیم و همون ۶۴ گیگ، سایز بخش‌هامون ۱ روز باشه، کوئری‌هامون بهتر میشه.

ایندکس‌ها هم توی سایز بخش‌ها تاثیر دارن. مخصوصا ایندکس‌های سنگین مثل PostGIS. برای مطالعه بیشتر اینجا رو مطالعه کنید.

برای مطالعه بیشتر در مورد سایز بخش‌ها اینجا و اینجا می‌تونه کمک کننده باشه.
درمورد space partitioning چون اختیاریه و مطلب هم طولانی میشه چیزی نمیگم ولی از اینجا می‌تونید درموردشون مطالعه داشته باشید. توصیه ام اینه حتما یک نگاه حتی سرسری هم که شده بندازین.

Bucket & Origin

این دو مفهوم قالب(bucket) و مبدا(origin) خودشون رو موقع واکشی(fetch) اطلاعات نشون میدن. به عنوان مثال وقتی که می‌خوایم اطلاعات چند ماه اخیر رو در قالب هفتگی داشته باشیم. TimescaleDB این ویژگی رو داره که بازه زمانی رو بهش بدی و بگی اطلاعات در قالب‌های روزانه، هفتگی و ماهانه و سالانه بهم برگردون. اما این موضوع رو چرا مطرح کردم؟ به خاطر تفاوت تقویم شمسی و میلادی. در تقویم میلادی شروع هفته دوشنبه‌ست(منظور اکثر کشورهاست) یعنی وقتی به TimescaleDB میگیم اطلاعات در قالب هفتگی بهمون بده قالب‌ها(bucket) از روز دوشنبه شروع میشن یا این موضوع در قالب ماهانه هم وجود داره و ماه‌های میلادی مدنظر قرار می‌گیرن. برای حل این مشکل TimescaleDB با پارامتر مبدا(origin) کار می‌کنه. به صورت پیشفرص مقادیر این پارامتر برای قالب‌های قرن و سال و ماه از اول ماه ژانویه(January) سال ۲۰۰۰ و برای بقیه قالب‌ها از ۳ ژانویه(January) سال ۲۰۰۰ تنظیم شده. پس ما برای تغییر و گرفتن اطلاعات در قالب درست باید این پارامتر origin رو عوض کنیم.

نکته آخر هم اینکه TimescaleDB این امکان رو هم میده که برای قالب‌ها در بازه‌های زمانی که ممکنه دیتا نداشته باشیم، از gapfill استفاده کنیم و با صفر برگردونه، ولی فکر کنم این پارامتر origin برای gapfill هنوز پیاده‌سازی نشده.

بخش پایانی

درمورد TimescaleDB نکات زیاده، مثلا ما اصلا درمورد فشرده‌سازی دیتا اصلا هیچ حرفی نزدیم یا انتقال اطلاعات، یا replication یا distribute hypertable‌ها و خیلی چیزهای دیگه(طبیعتا منم بلد نیستم تا در موردشون حرف بزنم D:).

ولی مستندات و بلاگ خوبی دارن که توضیحات رو اونجا دادن.

منابع

  • https://docs.timescale.com/
timescale dbtimeseries dbtimescaledbpostgresqlpostgres
یه وحید از نوع برنامه نویسش :)
شاید از این پست‌ها خوشتان بیاید