Skip to content
ClickHouse Docs
ClickHouse DocsClickHouse Docs

محرك الجدول ReplacingMergeTree

يختلف هذا المحرك عن MergeTree في أنه يزيل الإدخالات المكررة التي لها القيمة نفسها لـ مفتاح الفرز (قسم الجدول ORDER BY، وليس PRIMARY KEY).

لا تحدث إزالة البيانات المكررة إلا أثناء عملية دمج. وتحدث عملية الدمج في الخلفية في وقت غير معروف، لذلك لا يمكنك التخطيط لها. وقد تظل بعض البيانات غير مُعالَجة. ورغم أنه يمكنك تشغيل عملية دمج غير مجدولة باستخدام الاستعلام OPTIMIZE، فلا تعوّل على ذلك، لأن الاستعلام OPTIMIZE سيقرأ كمية كبيرة من البيانات ويكتبها.

لذلك، يُعد ReplacingMergeTree مناسبًا لإزالة البيانات المكررة في الخلفية لتوفير المساحة، لكنه لا يضمن خلو البيانات من التكرار.

إنشاء جدول

CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]
(
    name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1],
    name2 [type2] [DEFAULT|MATERIALIZED|ALIAS expr2],
    ...
) ENGINE = ReplacingMergeTree([ver [, is_deleted]])
[PARTITION BY expr]
[ORDER BY expr]
[PRIMARY KEY expr]
[SAMPLE BY expr]
[SETTINGS name=value, ...]

للاطلاع على وصف مَعلمات الطلب، راجع وصف التعليمة.

معلمات ReplacingMergeTree

ver

ver — عمود يحتوي على رقم الإصدار. النوع UInt* أو Date أو DateTime أو DateTime64. مُعامِل اختياري.

عند الدمج، يحتفظ ReplacingMergeTree بصف واحد فقط من بين جميع الصفوف التي لها مفتاح الفرز نفسه:

  • الصف الأخير في التحديد، إذا لم يتم تعيين ver. والتحديد هو مجموعة من الصفوف ضمن مجموعة من الأجزاء المشاركة في عملية الدمج. ويكون الجزء الذي أُنشئ مؤخرًا (آخر عملية insert) هو الأخير في التحديد. لذلك، بعد إزالة التكرار، يبقى آخر صف أُدرج من أحدث عملية insert لكل مفتاح فرز فريد.
  • الصف ذو أكبر إصدار، إذا تم تحديد ver. وإذا كانت قيمة ver متطابقة في عدة صفوف، فستُطبَّق عليها قاعدة "إذا لم يتم تحديد ver"، أي سيبقى الصف المُدرَج الأحدث.

مثال:

-- without ver - the last inserted 'wins'
CREATE TABLE myFirstReplacingMT
(
    `key` Int64,
    `someCol` String,
    `eventTime` DateTime
)
ENGINE = ReplacingMergeTree
ORDER BY key;

INSERT INTO myFirstReplacingMT Values (1, 'first', '2020-01-01 01:01:01');
INSERT INTO myFirstReplacingMT Values (1, 'second', '2020-01-01 00:00:00');

SELECT * FROM myFirstReplacingMT FINAL;

is_deleted

is_deleted — اسم عمود يُستخدم أثناء عملية الدمج لتحديد ما إذا كانت البيانات في هذا الصف تمثل الحالة أم يجب حذفها؛ 1 يشير إلى صف "محذوف"، و0 يشير إلى صف "حالة".

نوع بيانات العمود — UInt8.

مثال:

-- with ver and is_deleted
CREATE OR REPLACE TABLE myThirdReplacingMT
(
    `key` Int64,
    `someCol` String,
    `eventTime` DateTime,
    `is_deleted` UInt8
)
ENGINE = ReplacingMergeTree(eventTime, is_deleted)
ORDER BY key
SETTINGS allow_experimental_replacing_merge_with_cleanup = 1;

INSERT INTO myThirdReplacingMT Values (1, 'first', '2020-01-01 01:01:01', 0);
INSERT INTO myThirdReplacingMT Values (1, 'first', '2020-01-01 01:01:01', 1);

select * from myThirdReplacingMT final;

0 rows in set. Elapsed: 0.003 sec.

-- delete rows with is_deleted
OPTIMIZE TABLE myThirdReplacingMT FINAL CLEANUP;

INSERT INTO myThirdReplacingMT Values (1, 'first', '2020-01-01 00:00:00', 0);

select * from myThirdReplacingMT final;

عبارات الاستعلام

عند إنشاء جدول ReplacingMergeTree، تكون العبارات نفسها مطلوبة، كما هو الحال عند إنشاء جدول MergeTree.

الطريقة المتقادمة لإنشاء جدول
CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]
(
    name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1],
    name2 [type2] [DEFAULT|MATERIALIZED|ALIAS expr2],
    ...
) ENGINE [=] ReplacingMergeTree(date-column [, sampling_expression], (primary, key), index_granularity, [ver])

جميع المَعلمات، باستثناء ver، لها المعنى نفسه كما في MergeTree.

  • ver - العمود الذي يحتوي على الإصدار. مَعلمة اختيارية. للاطلاع على الوصف، راجع النص أعلاه.

إزالة التكرار وقت الاستعلام & FINAL

عند وقت الدمج، يحدّد محرك ReplacingMergeTree الصفوف المكررة باستخدام قيم أعمدة ORDER BY (المستخدمة في إنشاء الجدول) بوصفها معرّفًا فريدًا، ولا يحتفظ إلا بأعلى إصدار. لكن هذا لا يوفّر سوى صحة نهائية بمرور الوقت، إذ لا يضمن إزالة تكرار الصفوف، لذا ينبغي عدم الاعتماد عليه. ولذلك قد تُنتج الاستعلامات نتائج غير صحيحة بسبب احتساب صفوف التحديث والحذف ضمن الاستعلامات.

وللحصول على نتائج صحيحة، سيحتاج المستخدمون إلى استكمال عمليات الدمج في الخلفية بإزالة التكرار وحذف الصفوف المحذوفة وقت الاستعلام. ويمكن تحقيق ذلك باستخدام العامل FINAL. على سبيل المثال، تأمل المثال التالي:

CREATE TABLE rmt_example
(
    `number` UInt16
)
ENGINE = ReplacingMergeTree
ORDER BY number

INSERT INTO rmt_example SELECT floor(randUniform(0, 100)) AS number
FROM numbers(1000000000)

0 rows in set. Elapsed: 19.958 sec. Processed 1.00 billion rows, 8.00 GB (50.11 million rows/s., 400.84 MB/s.)

يعطي الاستعلام بدون FINAL عددًا غير صحيح (تختلف النتيجة الدقيقة بحسب عمليات الدمج):

SELECT count()
FROM rmt_example

تؤدي إضافة FINAL إلى نتيجة صحيحة:

SELECT count()
FROM rmt_example
FINAL

لمزيد من التفاصيل حول FINAL، بما في ذلك كيفية تحسين أداء FINAL، نوصي بقراءة دليلنا التفصيلي حول ReplacingMergeTree.

Navigation