Data Engineering

ClickHouse برای داده‌های سری زمانی: بهینه‌سازی طراحی اسکیم و فشرده‌سازی برای تله‌متری IoT

مدیریت حجم عظیمی از تله‌متری IoT به یک موتور پایگاه داده نیاز دارد که بتواند ورودی با پهنای باند بالا را در حالی که خوانش با تأخیر کم حفظ می‌کند، مدیریت کند. ClickHouse به عنوان یک پایگاه داده ستونی پیشرو برای این منظور ظاهر شده است، اما عملکرد آن به شدت به طراحی اسکیم و استراتژی‌های فشرده‌سازی بستگی دارد. در این مقاله، بررسی می‌کنیم که چگونه می‌توانید جداول ClickHouse خود را برای حداکثر کارایی داده‌های سری زمانی ساختار دهید.

انتخاب موتور جدول و ترتیب‌بندی مناسب

پایه‌ی یک بار کاری سری زمانی کارآمد در ClickHouse، خانواده موتورهای جدول MergeTree است. برای اکثر سناریوهای IoT، ReplicatedMergeTree یا ReplicatedCollapsingMergeTree (اگر به داده‌های قابل تغییر از طریق نسخه‌بندی نیاز دارید) گزینه‌های اصلی هستند. جزء حیاتی در اینجا بند ORDER BY است. برخلاف پایگاه‌های داده سنتی، ClickHouse داده‌ها را بر اساس کلید اصلی به صورت فیزیکی روی دیسک مرتب می‌کند. برای تله‌متری، شما می‌خواهید بر اساس شناسه دستگاه و زمان‌سنج ترتیب‌بندی کنید. این تضمین می‌کند که داده‌های یک دستگاه خاص پیوسته هستند و امکان اسکن‌های بازه‌ای کارآمد را فراهم می‌کنند.

CREATE TABLE iot_telemetry (
    device_id UUID,
    event_time DateTime,
    sensor_type String,
    temperature Float64,
    humidity Float64,
    battery_level UInt8
) ENGINE = ReplicatedMergeTree('/clickhouse/tables/{shard}/iot_telemetry', '{replica}')
ORDER BY (device_id, event_time);

به استفاده از device_id و event_time در کلید ترتیب توجه کنید. اگر برای تمام خوانش‌های device_123 بین ساعت ۲ و ۳ بعدازظهر کوئری کنید، ClickHouse می‌تواند اکثر بلوک‌های داده روی دیسک را رد کند و I/O را به شدت کاهش دهد.

استفاده از فشرده‌سازی و دانه‌بندی (Granularity)

ذخیره‌سازی ستونی به ClickHouse اجازه می‌دهد کدک‌های فشرده‌سازی مختلف را برای ستون‌های مختلف اعمال کند. ستون‌های با کاردینالیته بالا مانند sensor_type یا شناسه‌های رشته‌ای از فشرده‌سازی LZ4 یا ZSTD بهره می‌برند، در حالی که ستون‌های با کاردینالیته پایین مانند battery_level (که احتمالاً مقادیر تکراری دارند) ممکن است از کدگذاری واژه‌نامه یا کدک‌های ساده‌تر بهره ببرند. علاوه بر این، تنظیم granularity حیاتی است. اندازه پیش‌فرض گرانول ۸۱۹۲ ردیف است. برای تله‌متری با فرکانس بالا که اغلب کوئری‌های بازه‌های زمانی کوچک انجام می‌دهید، اندازه گرانول کوچک‌تر (مثلاً ۴۰۹۶) می‌تواند عملکرد خوانش را به قیمت کمی افزایش در سربار متادیتا بهبود بخشد.

برای تنظیم صریح فشرده‌سازی برای ستون‌های خاص، می‌توانید از پارامتر CODEC در تعریف ستون استفاده کنید:

ALTER TABLE iot_telemetry
MODIFY COLUMN sensor_type CODEC(LZ4);

ALTER TABLE iot_telemetry
MODIFY COLUMN temperature CODEC(ZSTD);

ZSTD معمولاً نسبت فشرده‌سازی بهتری نسبت به LZ4 برای داده‌های عددی ارائه می‌دهد اما کندتر است. برای داشبوردهای بلادرنگ که سرعت اولویت دارد، LZ4 اغلب برای ستون‌های پرمصرف ترجیح داده می‌شود.

پارتیشن‌بندی برای مدیریت چرخه حیات داده

پارتیشن‌بندی بر اساس زمان برای داده‌های IoT ضروری است تا سیاست‌های TTL (زمان ماندگاری) و حذف کارآمد داده را تسهیل کند. با پارتیشن‌بندی بر روی event_time، می‌توانید به راحتی داده‌های قدیمی را حذف کنید یا آن‌ها را به ذخیره‌سازی سرد منتقل کنید بدون اینکه کل جدول را اسکن کنید. یک الگوی رایج، پارتیشن‌بندی بر اساس ماه یا روز، بسته به حجم داده است.

ALTER TABLE iot_telemetry
PARTITION BY toMonth(event_time);

ALTER TABLE iot_telemetry
MODIFY TTL event_time + INTERVAL 90 DAY;

این تنظیم تضمین می‌کند که داده‌های قدیمی‌تر از ۹۰ روز به صورت خودکار حذف می‌شوند و هزینه‌های ذخیره‌سازی داغ را قابل مدیریت نگه می‌دارند. ترکیب این با کلید ORDER BY یک چیدمان فیزیکی بسیار کارآمد ایجاد می‌کند که در آن داده‌ها هم برای جستجوی سریع مرتب شده‌اند و هم برای مدیریت آسان پارتیشن‌بندی شده‌اند.

نتیجه‌گیری

بهینه‌سازی ClickHouse برای تله‌متری IoT فقط درباره انتخاب پایگاه داده مناسب نیست؛ بلکه درباره همسوسازی طراحی اسکیم شما با الگوهای کوئری شماست. با انتخاب دقیق کلید ORDER BY، تنظیم کدک‌های فشرده‌سازی و پیاده‌سازی پارتیشن‌بندی استراتژیک، می‌توانید سیستمی محکم بسازید که قادر به مدیریت میلیون‌ها نقطه داده در ثانیه با زمان کوئری زیر یک ثانیه باشد. با این اصول بنیادین شروع کنید و لاگ‌های کوئری خود را پایش کنید تا فرصت‌های بهینه‌سازی بیشتر را شناسایی کنید.

Share: