مقارنة المخططات المُطبَّعة مقابل المخططات منزوعة التطبيع
من الأساليب الشائعة التي شاع استخدامها مع حلول NoSQL إلغاء تطبيع البيانات عند غياب دعم
JOIN، وذلك عبر تخزين جميع الإحصاءات أو الصفوف المرتبطة داخل صف أصلي على هيئة أعمدة وكائنات متداخلة. على سبيل المثال، في مخطط نموذجي لمدونة، يمكننا تخزين جميع Comments باعتبارها Array من الكائنات ضمن المنشورات المقابلة لها.
متى تستخدم إلغاء التطبيع
- أزِل إلغاء التطبيع عن الجداول التي نادرًا ما تتغير، أو التي يمكن فيها تحمّل تأخير قبل إتاحة البيانات للاستعلامات التحليلية، أي عندما يمكن إعادة تحميل البيانات بالكامل على شكل دفعة.
- تجنّب إلغاء التطبيع في العلاقات متعدد-إلى-متعدد، لأن ذلك قد يؤدي إلى الحاجة إلى تحديث عدد كبير من الصفوف إذا تغيّر صف واحد في المصدر.
- تجنّب إلغاء التطبيع في العلاقات عالية الكاردينالية. فإذا كان كل صف في جدول ما يرتبط بآلاف الإدخالات في جدول آخر، فسيتعيّن تمثيلها على شكل
Array— إما من نوع بدائي أوTuple. وبوجه عام، لا يُنصح عادةً بالمصفوفات التي تحتوي على أكثر من 1000Tuple. - بدلًا من إلغاء التطبيع لجميع الأعمدة على هيئة كائنات متداخلة، فكّر في إلغاء التطبيع لإحصائية واحدة فقط باستخدام العروض المادية (انظر أدناه).
تجنّب إلغاء التطبيع للبيانات التي تُحدَّث بشكل متكرر
- تشغيل عبارات JOIN الصحيحة عند تغيّر صف في جدول. ومن المثالي ألّا يؤدي ذلك إلى تحديث جميع الكائنات المرتبطة بعملية JOIN، بل فقط تلك التي تأثرت. ويتطلب تعديل عمليات JOIN لتطبيق عامل تصفية على الصفوف الصحيحة بكفاءة، وتحقيق ذلك في ظل معدل نقل مرتفع، أدوات خارجية أو جهدًا هندسيًا.
- يجب إدارة تحديثات الصفوف في ClickHouse بعناية، مما يضيف مزيدًا من التعقيد.
لذلك، تكون عملية التحديث على شكل دفعات أكثر شيوعًا، حيث يُعاد تحميل جميع الكائنات التي خضعت لإلغاء التطبيع بشكل دوري.
حالات عملية لإلغاء التطبيع
Posts جرى بالفعل إلغاء تطبيعه بإحصاءات مثل AnswerCount وCommentCount — إذ تُوفَّر البيانات المصدر بهذا الشكل. لكن عمليًا، قد نرغب في تطبيع هذه المعلومات، لأنها على الأرجح ستكون عرضة لتغييرات متكررة. كما أن كثيرًا من هذه الأعمدة متاح أيضًا عبر جداول أخرى؛ فعلى سبيل المثال، تتوفر تعليقات المنشور من خلال العمود PostId والجدول Comments. ولأغراض هذا المثال، نفترض أن المنشورات يُعاد تحميلها ضمن عملية مجمّعة.
وسنقتصر هنا على إلغاء تطبيع الجداول الأخرى إلى Posts، لأننا نعدّه جدولنا الرئيسي لأغراض التحليلات. وقد يكون إلغاء التطبيع في الاتجاه المعاكس مناسبًا أيضًا لبعض الاستعلامات، مع انطباق الاعتبارات نفسها المذكورة أعلاه.
في كل مثال من الأمثلة التالية، افترض وجود استعلام يتطلب استخدام الجدولين معًا في عملية join.
Posts وVotes
Score حاليًا إحصائية من هذا النوع، أي إجمالي الأصوات المؤيدة مطروحًا منه الأصوات المعارضة. ومن الناحية المثالية، نحتاج فقط إلى استرجاع هذه الإحصاءات في وقت الاستعلام من خلال عملية بحث بسيطة (راجع القواميس).
Users وBadges
Users وBadges:
نُدرج البيانات أولًا باستخدام الأمر التالي:
قد نرغب في إلغاء تطبيع إحصاءات من جدول Badges إلى جدول Users، مثل عدد الشارات. ونتناول مثالًا كهذا عند استخدام القواميس لهذه المجموعة من البيانات وقت الإدراج.
Posts وPostLinks
PostLinks بين عناصر Posts التي يعتبرها المستخدمون ذات صلة أو مكررة. يوضّح الاستعلام التالي المخطط وأمر التحميل:
مثال بسيط على إحصائية
INSERT INTO SELECT لإجراء JOIN بين إحصائية التكرار وبيانات posts لدينا.
استغلال الأنواع المعقدة للعلاقات من واحد إلى متعدد
- Named Tuples - تتيح تمثيل بنية مرتبطة كمجموعة من الأعمدة.
- Array(Tuple) أو Nested - مصفوفة من Named Tuples، وتُعرف أيضًا باسم Nested، بحيث يمثّل كل إدخال كائنًا. وينطبق ذلك على العلاقات من واحد إلى متعدد.
PostLinks ضمن Posts.
يمكن أن يحتوي كل منشور على عدد من الروابط إلى منشورات أخرى كما هو موضح سابقًا في مخطط PostLinks. وباستخدام النوع Nested، يمكننا تمثيل هذه المنشورات المرتبطة والمكررة كما يلي:
لاحظ استخدام الإعداد flatten_nested=0. نوصي بتعطيل تسطيح البيانات المتداخلة.
يمكننا تنفيذ عملية إلغاء التطبيع هذه باستخدام استعلام INSERT INTO SELECT مع OUTER JOIN:
لاحظ الزمن هنا. لقد تمكّنا من إلغاء تطبيع 66 مليون صف خلال نحو دقيقتين. وكما سنرى لاحقًا، فهذه عملية يمكننا جدولة تشغيلها.لاحظ استخدام دوال
groupArray لطيّ PostLinks إلى مصفوفة واحدة لكل PostId قبل الربط. ثم تُرشَّح هذه المصفوفة إلى قائمتين فرعيتين: LinkedPosts وDuplicatePosts، مع استبعاد أي نتائج فارغة ناتجة عن الربط الخارجي أيضًا.
يمكننا اختيار بعض الصفوف للاطّلاع على بنيتنا الجديدة بعد إلغاء التطبيع:
تنظيم وجدولة إلغاء التطبيع
المعالجة الدُفعية
INSERT INTO SELECT. وهذا مناسب لعمليات التحويل الدُفعية الدورية.
لدى المستخدمين عدة خيارات لتنسيق ذلك في ClickHouse، بافتراض أن عملية تحميل دُفعية دورية مقبولة:
- العروض المادية القابلة للتحديث - يمكن استخدام العروض المادية القابلة للتحديث لجدولة استعلام بشكل دوري مع إرسال النتائج إلى الجدول الهدف. وعند تنفيذ الاستعلام، يضمن العرض تحديث الجدول الهدف ذريًا. ويوفر ذلك وسيلة أصلية في ClickHouse لجدولة هذا العمل.
- أدوات خارجية - استخدام أدوات مثل dbt وAirflow لجدولة التحويل بشكل دوري. ويضمن تكامل ClickHouse مع dbt تنفيذ ذلك ذريًا، مع إنشاء إصدار جديد من الجدول الهدف ثم تبديله ذريًا مع الإصدار الذي يستقبل الاستعلامات (عبر الأمر EXCHANGE).