نظرة عامة على TTL
يشير TTL (مدة البقاء) إلى إمكانية نقل الصفوف أو الأعمدة أو حذفها أو تلخيصها بعد انقضاء مدة زمنية معيّنة. ورغم أن مصطلح "مدة البقاء" يوحي بأنه يقتصر على حذف البيانات القديمة، فإن لـ TTL عدة حالات استخدام:
- إزالة البيانات القديمة: لا مفاجأة هنا، إذ يمكنك حذف الصفوف أو الأعمدة بعد مدة زمنية محددة
- نقل البيانات بين الأقراص: بعد مرور فترة معيّنة، يمكنك نقل البيانات بين وحدات التخزين، وهو ما يفيد في نشر معمارية hot/warm/cold
- تلخيص البيانات: يمكنك تلخيص بياناتك الأقدم في تجميعات وعمليات احتساب مفيدة متنوعة قبل حذفها
بنية TTL
يمكن أن تَرِد عبارة TTL بعد تعريف عمود و/أو في نهاية تعريف الجدول. استخدم عبارة INTERVAL لتحديد فترة زمنية (ويجب أن تكون من نوع البيانات Date أو DateTime). على سبيل المثال، يحتوي الجدول التالي على عمودين
مع عبارتي TTL:
CREATE TABLE example1 (
timestamp DateTime,
x UInt32 TTL timestamp + INTERVAL 1 MONTH,
y String TTL timestamp + INTERVAL 1 DAY,
z String
)
ENGINE = MergeTree
ORDER BY tuple()- يحتوي العمود x على مدة بقاء قدرها شهر واحد بدءًا من عمود الطابع الزمني
- يحتوي العمود y على مدة بقاء قدرها يوم واحد بدءًا من عمود الطابع الزمني
- عند انقضاء الفاصل الزمني، تنتهي صلاحية العمود. يستبدل ClickHouse قيمة العمود بالقيمة الافتراضية لنوع بياناته. وإذا انتهت صلاحية جميع قيم العمود في جزء البيانات، يحذف ClickHouse هذا العمود من جزء البيانات في نظام الملفات.
تشغيل أحداث TTL
إن حذف الصفوف منتهية الصلاحية أو تجميعها لا يحدث فورًا، بل لا يتم إلا أثناء عمليات دمج الجدول. وإذا كان لديك جدول لا تُجرى له عمليات دمج بشكل نشط (لأي سبب كان)، فهناك إعدادان يُشغّلان أحداث TTL:
merge_with_ttl_timeout: الحد الأدنى للتأخير بالثواني قبل تكرار عملية دمج مع TTL للحذف. القيمة الافتراضية هي 14400 ثانية (4 ساعات).merge_with_recompression_ttl_timeout: الحد الأدنى للتأخير بالثواني قبل تكرار عملية دمج مع TTL لإعادة الضغط (القواعد التي تُجمّع البيانات قبل حذفها). القيمة الافتراضية: 14400 ثانية (4 ساعات).
لذلك، وبشكل افتراضي، ستُطبَّق قواعد TTL على جدولك مرة واحدة على الأقل كل 4 ساعات. ما عليك سوى تعديل الإعدادات أعلاه إذا كنت بحاجة إلى تطبيق قواعد TTL بوتيرة أعلى.
إزالة الصفوف
لإزالة صفوف كاملة من جدول بعد فترة زمنية معينة، حدِّد قاعدة TTL على مستوى الجدول:
CREATE TABLE customers (
timestamp DateTime,
name String,
balance Int32,
address String
)
ENGINE = MergeTree
ORDER BY timestamp
TTL timestamp + INTERVAL 12 HOURبالإضافة إلى ذلك، يمكن تعريف قاعدة TTL استنادًا إلى قيمة السجل. ويمكن تنفيذ ذلك بسهولة عبر تحديد شرط WHERE. ويُسمح بوجود شروط متعددة:
CREATE TABLE events
(
`event` String,
`time` DateTime,
`value` UInt64
)
ENGINE = MergeTree
ORDER BY (event, time)
TTL time + INTERVAL 1 MONTH DELETE WHERE event != 'error',
time + INTERVAL 6 MONTH DELETE WHERE event = 'error'إزالة الأعمدة
بدلًا من حذف الصف بأكمله، لنفترض أنك تريد فقط انتهاء صلاحية عمودي الرصيد والعنوان. لنعدّل جدول customers ونضيف قيمة TTL لكلا العمودين لمدة ساعتين:
ALTER TABLE customers
MODIFY COLUMN balance Int32 TTL timestamp + INTERVAL 2 HOUR,
MODIFY COLUMN address String TTL timestamp + INTERVAL 2 HOURتنفيذ عملية تلخيص
لنفترض أننا نريد حذف الصفوف بعد مرور فترة زمنية معينة، مع الاحتفاظ ببعض البيانات لأغراض إعداد التقارير. نحن لا نحتاج إلى كل التفاصيل، بل إلى بعض النتائج المجمّعة فقط من البيانات التاريخية. يمكن تنفيذ ذلك بإضافة عبارة GROUP BY إلى تعبير TTL، إلى جانب بعض الأعمدة في جدولك لتخزين النتائج المجمّعة.
لنفترض أننا نريد، في جدول hits التالي، حذف الصفوف القديمة مع الاحتفاظ بمجموع القيم والقيمة العظمى لأعمدة hits قبل إزالة الصفوف. سنحتاج إلى حقل لتخزين هذه القيم، كما سنحتاج إلى إضافة عبارة GROUP BY إلى عبارة TTL لتنفيذ تلخيص للمجموع والقيمة العظمى:
CREATE TABLE hits (
timestamp DateTime,
id String,
hits Int32,
max_hits Int32 DEFAULT hits,
sum_hits Int64 DEFAULT hits
)
ENGINE = MergeTree
PRIMARY KEY (id, toStartOfDay(timestamp), timestamp)
TTL timestamp + INTERVAL 1 DAY
GROUP BY id, toStartOfDay(timestamp)
SET
max_hits = max(max_hits),
sum_hits = sum(sum_hits);بعض الملاحظات حول جدول hits:
- يجب أن تكون الأعمدة في عبارة
GROUP BYضمن عبارةTTLبادئة لـPRIMARY KEY، ونريد تجميع نتائجنا حسب بداية اليوم. لذلك أُضيفتtoStartOfDay(timestamp)إلى المفتاح الأساسي - أضفنا حقلين لتخزين النتائج المجمّعة:
max_hitsوsum_hits - إن تعيين القيمة الافتراضية لـ
max_hitsوsum_hitsإلىhitsضروري لعمل هذا المنطق، استنادًا إلى كيفية تعريف عبارةSET
تنفيذ معمارية hot/warm/cold
من الممارسات الشائعة عند العمل مع كميات كبيرة من البيانات نقلها كلما تقادمت. في ما يلي خطوات تنفيذ معمارية hot/warm/cold في ClickHouse باستخدام العبارتين TO DISK وTO VOLUME في الأمر TTL. (وبالمناسبة، لا يقتصر الأمر على hot وcold فقط — إذ يمكنك استخدام TTL لنقل البيانات وفقًا لأي حالة استخدام لديك.)
- يشير الخياران
TO DISKوTO VOLUMEإلى أسماء الأقراص أو وحدات التخزين المعرّفة في ملفات تكوين ClickHouse. أنشئ ملفًا جديدًا باسمmy_system.xml(أو بأي اسم ملف آخر) لتعريف الأقراص، ثم عرّف وحدات تخزين تستخدم هذه الأقراص. ضع ملف XML في/etc/clickhouse-server/config.d/لتطبيق الإعدادات على نظامك:
<clickhouse>
<storage_configuration>
<disks>
<default>
</default>
<hot_disk>
<path>./hot/</path>
</hot_disk>
<warm_disk>
<path>./warm/</path>
</warm_disk>
<cold_disk>
<path>./cold/</path>
</cold_disk>
</disks>
<policies>
<default>
<volumes>
<default>
<disk>default</disk>
</default>
<hot_volume>
<disk>hot_disk</disk>
</hot_volume>
<warm_volume>
<disk>warm_disk</disk>
</warm_volume>
<cold_volume>
<disk>cold_disk</disk>
</cold_volume>
</volumes>
</default>
</policies>
</storage_configuration>
</clickhouse>- يشير التكوين أعلاه إلى ثلاثة أقراص تشير إلى مجلدات يمكن لـ ClickHouse القراءة منها والكتابة إليها. ويمكن أن تحتوي وحدات التخزين على قرص واحد أو أكثر - وقد عرّفنا وحدة تخزين لكل قرص من الأقراص الثلاثة. لنستعرض الأقراص:
SELECT name, path, free_space, total_space
FROM system.disks┌─name────────┬─path───────────┬───free_space─┬──total_space─┐
│ cold_disk │ ./data/cold/ │ 179143311360 │ 494384795648 │
│ default │ ./ │ 179143311360 │ 494384795648 │
│ hot_disk │ ./data/hot/ │ 179143311360 │ 494384795648 │
│ warm_disk │ ./data/warm/ │ 179143311360 │ 494384795648 │
└─────────────┴────────────────┴──────────────┴──────────────┘- والآن… لنتأكد من وحدات التخزين:
SELECT
volume_name,
disks
FROM system.storage_policies┌─volume_name─┬─disks─────────┐
│ default │ ['default'] │
│ hot_volume │ ['hot_disk'] │
│ warm_volume │ ['warm_disk'] │
│ cold_volume │ ['cold_disk'] │
└─────────────┴───────────────┘- سنضيف الآن قاعدة
TTLتنقل البيانات بين وحدات التخزين الساخنة والدافئة والباردة:
ALTER TABLE my_table
MODIFY TTL
trade_date TO VOLUME 'hot_volume',
trade_date + INTERVAL 2 YEAR TO VOLUME 'warm_volume',
trade_date + INTERVAL 4 YEAR TO VOLUME 'cold_volume';- يجب أن تدخل قاعدة
TTLالجديدة حيّز التنفيذ، ولكن يمكنك فرض ذلك للتأكد:
ALTER TABLE my_table
MATERIALIZE TTL- تحقّق من انتقال بياناتك إلى الأقراص المتوقعة باستخدام الجدول
system.parts:
Using the system.parts table, view which disks the parts are on for the crypto_prices table:
SELECT
name,
disk_name
FROM system.parts
WHERE (table = 'my_table') AND (active = 1)سيكون الإخراج كما يلي:
┌─name────────┬─disk_name─┐
│ all_1_3_1_5 │ warm_disk │
│ all_2_2_0 │ hot_disk │
└─────────────┴───────────┘