- استخدم أنواعًا صارمة: اختر دائمًا نوع البيانات الصحيح للأعمدة. ينبغي أن تستخدم الحقول الرقمية وحقول التاريخ أنواعًا رقمية وأنواع تاريخ مناسبة بدلًا من أنواع String العامة. وهذا يضمن دلالات صحيحة لعمليات التصفية وaggregations.
- تجنّب الأعمدة Nullable: تضيف الأعمدة Nullable حملًا إضافيًا من خلال الاحتفاظ بأعمدة منفصلة لتتبّع القيم null. لا تستخدم Nullable إلا إذا كان ذلك مطلوبًا صراحةً للتمييز بين الحالة الفارغة والحالة null. وبخلاف ذلك، فعادةً ما تكون القيم الافتراضية أو القيم المكافئة للصفر كافية. ولمزيد من المعلومات حول سبب وجوب تجنّب هذا النوع ما لم تكن هناك حاجة إليه، راجع تجنّب الأعمدة Nullable.
- قلّل precision الرقمية إلى الحد الأدنى: اختر الأنواع الرقمية ذات أقل عدد ممكن من البتات مع الحفاظ على استيعاب نطاق البيانات المتوقع. على سبيل المثال، فضّل UInt16 بدلًا من Int32 إذا لم تكن القيم السالبة مطلوبة وكان النطاق يقع ضمن 0–65535.
- حسّن precision التاريخ والوقت: اختر نوع التاريخ أو datetime الأقل دقة الذي يلبّي متطلبات الاستعلامات. استخدم Date أو Date32 للحقول التي تحتوي على التاريخ فقط، وفضّل DateTime على DateTime64 ما لم تكن دقة المللي ثانية أو أدق ضرورية.
- استفد من LowCardinality والأنواع المتخصصة: بالنسبة إلى الأعمدة التي تحتوي على أقل من نحو 10,000 قيمة فريدة، استخدم أنواع LowCardinality لتقليل التخزين بشكل كبير عبر dictionary encoding. وبالمثل، استخدم FixedString فقط عندما تكون قيم العمود سلاسل ثابتة الطول تمامًا (مثل رموز البلدان أو العملات)، وفضّل أنواع Enum للأعمدة التي تحتوي على مجموعة محدودة من القيم الممكنة لتمكين تخزين فعّال والتحقق المدمج من صحة البيانات.
- استخدم Enum للتحقق من صحة البيانات: يمكن استخدام النوع Enum لترميز الأنواع المعدودة بكفاءة. ويمكن أن تكون Enums إما 8 أو 16 بتًا، وذلك حسب عدد القيم الفريدة المطلوب تخزينها. فكّر في استخدامه إذا كنت بحاجة إلى التحقق المرتبط به عند وقت insert (ستُرفض القيم غير المعرّفة)، أو إذا كنت ترغب في تنفيذ استعلامات تستفيد من ترتيب طبيعي في قيم Enum، مثل تخيّل عمودًا للملاحظات يحتوي على ردود المستخدمين Enum(’:(’ = 1, ’:|’ = 2, ’:)’ = 3).
مثال
DESCRIBE مخططًا مبدئيًا غير مُحسَّن.
يربط ClickHouse هذه القيم افتراضيًا بأنواع Nullable المكافئة. ويُفضَّل ذلك لأن المخطط يستند إلى عيّنة من الصفوف فقط.
لاحظ أننا نستخدم أدناه نمط glob *.parquet لقراءة جميع الملفات في المجلد stackoverflow/parquet/posts.
| العمود | هل هو رقمي | الحد الأدنى، الحد الأقصى | القيم الفريدة | القيم الفارغة | تعليق | النوع المُحسَّن |
|---|---|---|---|---|---|---|
PostTypeId | نعم | 1, 8 | 8 | لا | Enum('Question' = 1, 'Answer' = 2, 'Wiki' = 3, 'TagWikiExcerpt' = 4, 'TagWiki' = 5, 'ModeratorNomination' = 6, 'WikiPlaceholder' = 7, 'PrivilegeWiki' = 8) | |
AcceptedAnswerId | نعم | 0, 78285170 | 12282094 | نعم | ميّز بين NULL والقيمة 0 | UInt32 |
CreationDate | لا | 2008-07-31 21:42:52.667000000, 2024-03-31 23:59:17.697000000 | * | لا | لا حاجة إلى دقة المللي ثانية، استخدم DateTime | DateTime |
Score | نعم | -217, 34970 | 3236 | لا | Int32 | |
ViewCount | نعم | 2, 13962748 | 170867 | لا | UInt32 | |
Body | لا | - | * | لا | String | |
OwnerUserId | نعم | -1, 4056915 | 6256237 | نعم | Int32 | |
OwnerDisplayName | لا | - | 181251 | نعم | اعتبر NULL سلسلة فارغة | String |
LastEditorUserId | نعم | -1, 9999993 | 1104694 | نعم | 0 قيمة غير مستخدمة ويمكن استخدامها لتمثيل nulls | Int32 |
LastEditorDisplayName | لا | * | 70952 | نعم | اعتبر NULL سلسلة فارغة. تم اختبار LowCardinality ولم يحقق أي فائدة | String |
LastEditDate | لا | 2008-08-01 13:24:35.051000000, 2024-04-06 21:01:22.697000000 | - | لا | لا حاجة إلى دقة الملّي ثانية، استخدم DateTime | DateTime |
LastActivityDate | لا | 2008-08-01 12:19:17.417000000, 2024-04-06 21:01:22.697000000 | * | لا | لا حاجة إلى دقة المللي ثانية، استخدم DateTime | DateTime |
Title | لا | - | * | لا | اعتبار Null كسلسلة فارغة | String |
الوسوم | لا | - | * | لا | اعتبار Null كسلسلة فارغة | String |
AnswerCount | نعم | 0, 518 | 216 | لا | اعتبر Null و0 متساويين | UInt16 |
CommentCount | نعم | 0, 135 | 100 | لا | اعتبر NULL و0 متماثلين | UInt8 |
FavoriteCount | نعم | 0, 225 | 6 | نعم | اعتبر NULL و0 متساويين | UInt8 |
ContentLicense | لا | - | 3 | لا | يقدّم LowCardinality أداءً أفضل من FixedString | LowCardinality(String) |
ParentId | لا | * | 20696028 | نعم | اعتبر NULL سلسلة نصية فارغة | String |
CommunityOwnedDate | لا | 2008-08-12 04:59:35.017000000, 2024-04-01 05:36:41.380000000 | - | نعم | يمكن اعتماد القيمة الافتراضية 1970-01-01 للقيم NULL. لا حاجة إلى دقة الملّي ثانية، استخدم DateTime | DateTime |
ClosedDate | لا | 2008-09-04 20:56:44, 2024-04-06 18:49:25.393000000 | * | نعم | يُراعى استخدام القيمة الافتراضية 1970-01-01 لقيم NULL. لا حاجة إلى دقة الملّي ثانية، استخدم DateTime | DateTime |
نصيحةيعتمد تحديد النوع المناسب لعمودٍ ما على فهم نطاقه العددي وعدد القيم الفريدة فيه. للعثور على النطاق في جميع الأعمدة وعدد القيم المتميزة، يمكنك استخدام الاستعلام البسيط
SELECT * APPLY min, * APPLY max, * APPLY uniq FROM table FORMAT Vertical. نوصي بتنفيذ ذلك على مجموعة فرعية أصغر من البيانات، لأن ذلك قد يكون مكلفًا.تجنب الأعمدة من النوع Nullable
Nullable column (مثل Nullable(String)) ينشئ عمودًا منفصلًا من النوع UInt8. ويجب معالجة هذا العمود الإضافي في كل مرة يتعامل فيها المستخدم مع عمود Nullable. ويؤدي ذلك إلى استهلاك مساحة تخزين إضافية، كما يؤثر سلبًا في الأداء في معظم الحالات.
لتجنّب الأعمدة Nullable، يُنصح بتعيين قيمة افتراضية لهذا العمود. على سبيل المثال، بدلًا من: