MySQL وتصميم قواعد البيانات

أنواع البيانات وتصميم الأعمدة

13 دقيقة الدرس 5 من 40

أنواع البيانات وتصميم الأعمدة

اختيار أنواع البيانات الصحيحة أمر بالغ الأهمية لأداء قاعدة البيانات، وكفاءة التخزين، وسلامة البيانات. في هذا الدرس، سنستكشف أنواع بيانات MySQL ونتعلم كيفية اختيار النوع الأمثل لكل عمود.

لماذا تهم أنواع البيانات

تأثير اختيارات نوع البيانات:كفاءة التخزين - الأنواع ذات الحجم المناسب توفر مساحة القرص - جداول أصغر = استعلامات أسرع - مهم لمجموعات البيانات الكبيرة ✓ الأداء - أنواع بيانات أصغر = مقارنات أسرع - أداء فهرس أفضل - صفوف أكثر تناسب الذاكرة ✓ سلامة البيانات - قيود النوع تمنع البيانات غير الصالحة - التحقق التلقائي - دلالات بيانات أوضح ✓ الجاهزية للمستقبل - اختر أنواعاً تستوعب النمو - تجنب عمليات الترحيل المؤلمة لاحقاً - توازن بين الاحتياجات الحالية والتوسع المستقبلي
القاعدة الذهبية: استخدم أصغر نوع بيانات يمكنه الاحتفاظ ببياناتك بشكل موثوق، مع مجال للنمو المعقول.

أنواع الأعداد الصحيحة: INT مقابل BIGINT مقابل TINYINT

يوفر MySQL عدة أنواع أعداد صحيحة بأحجام تخزين ونطاقات قيم مختلفة:

أنواع بيانات الأعداد الصحيحة: TINYINT - 1 بايت النطاق: -128 إلى 127 (موقّع) أو 0 إلى 255 (غير موقّع) استخدم لـ: العمر، رموز الحالة، منطقي (0/1)، عدادات صغيرة SMALLINT - 2 بايت النطاق: -32,768 إلى 32,767 (موقّع) أو 0 إلى 65,535 (غير موقّع) استخدم لـ: السنوات، عدادات المخزون الصغيرة، أرقام المنافذ MEDIUMINT - 3 بايت النطاق: -8,388,608 إلى 8,388,607 (موقّع) أو 0 إلى 16,777,215 (غير موقّع) استخدم لـ: تسلسلات متوسطة الحجم، معرفات المنتجات INT - 4 بايت (الأكثر شيوعاً) النطاق: -2,147,483,648 إلى 2,147,483,647 (موقّع) أو 0 إلى 4,294,967,295 (غير موقّع) استخدم لـ: المفاتيح الأساسية، المفاتيح الخارجية، معرفات المستخدم، معرفات الطلب BIGINT - 8 بايت النطاق: -9,223,372,036,854,775,808 إلى 9,223,372,036,854,775,807 (موقّع) استخدم لـ: تسلسلات كبيرة جداً، طوابع زمنية بالميلي ثانية، مبالغ مالية بالسنتات

أمثلة عملية للأعداد الصحيحة

اختيارات جيدة: CREATE TABLE users ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, -- ✓ 4 مليار مستخدم كحد أقصى age TINYINT UNSIGNED, -- ✓ 0-255 كافٍ login_count INT UNSIGNED DEFAULT 0, -- ✓ يتعامل مع ملايين عمليات تسجيل الدخول created_at TIMESTAMP -- ✓ نوع مدمج للتواريخ ); CREATE TABLE orders ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, -- ✓ للأنظمة عالية الحجم user_id INT UNSIGNED, -- ✓ يطابق users.id status TINYINT UNSIGNED, -- ✓ 0=معلق، 1=مدفوع، 2=مشحون total_cents BIGINT, -- ✓ تخزين المال بالسنتات FOREIGN KEY (user_id) REFERENCES users(id) ); اختيارات سيئة: CREATE TABLE users_bad ( id TINYINT AUTO_INCREMENT PRIMARY KEY, -- ❌ فقط 127 مستخدم كحد أقصى! age VARCHAR(10), -- ❌ يجب أن يكون رقمياً login_count BIGINT, -- ❌ مبالغة لمعظم الحالات created_at VARCHAR(50) -- ❌ استخدم TIMESTAMP/DATETIME );
خطأ شائع: استخدام VARCHAR للبيانات الرقمية مثل أرقام الهواتف أو الرموز البريدية. بينما قد تحتوي على أرقام غير أرقام، إذا لم تقم أبداً بعمليات رياضية عليها، فإن VARCHAR مقبول. ولكن للأرقام الحقيقية، استخدم أنواع رقمية.

أنواع السلاسل: VARCHAR مقابل CHAR مقابل TEXT

اختيار نوع السلسلة الصحيح يؤثر على التخزين والأداء:

CHAR(n) - طول ثابت - يستخدم دائماً n بايت بالضبط (مبطن بمسافات) - أسرع للبيانات ذات الطول الثابت - استخدم لـ: رموز البلدان (CHAR(2))، أعلام الحالة، تجزئات MD5 (CHAR(32)) مثال: CHAR(2) لـ "US"، "UK"، "FR" VARCHAR(n) - طول متغير - يستخدم 1-2 بايت + طول السلسلة الفعلي - الأكثر شيوعاً ومرونة - الحد الأقصى: 65,535 بايت - استخدم لـ: الأسماء، البريد الإلكتروني، URLs، الأوصاف مثال: VARCHAR(100) لعناوين البريد الإلكتروني TEXT - نص كبير - لا يمكن أن يكون له قيمة افتراضية - مخزن خارج الصف (أبطأ) - المتغيرات: TINYTEXT (255)، TEXT (64KB)، MEDIUMTEXT (16MB)، LONGTEXT (4GB) - استخدم لـ: مقالات المدونة، التعليقات، المحتوى الغني مثال: TEXT لـ article_body الاختلافات الرئيسية: - CHAR: ثابت، مبطن، سريع للسلاسل القصيرة - VARCHAR: متغير، فعال، الأكثر شيوعاً - TEXT: محتوى كبير، لا افتراضي، فهرسة أبطأ

أمثلة أنواع السلاسل

استخدام مثالي للسلاسل: CREATE TABLE products ( id INT PRIMARY KEY, sku CHAR(10), -- ✓ تنسيق ثابت: "PROD000123" name VARCHAR(200), -- ✓ أسماء المنتجات تختلف description TEXT, -- ✓ أوصاف طويلة slug VARCHAR(255) UNIQUE, -- ✓ معرف ملائم لـ URL short_desc VARCHAR(500) -- ✓ ملخص موجز ); CREATE TABLE users ( id INT PRIMARY KEY, email VARCHAR(255) UNIQUE, -- ✓ طول البريد الإلكتروني القياسي first_name VARCHAR(50), -- ✓ طول اسم معقول last_name VARCHAR(50), country_code CHAR(2), -- ✓ دائماً حرفان: "US"، "CA" phone VARCHAR(20), -- ✓ تنسيقات دولية تختلف bio TEXT, -- ✓ السيرة الذاتية للمستخدم يمكن أن تكون طويلة password_hash CHAR(60) -- ✓ bcrypt دائماً 60 حرفاً ); اختيارات سيئة: CREATE TABLE products_bad ( name CHAR(200), -- ❌ يهدر المساحة إذا كان الاسم "قلم" description VARCHAR(100), -- ❌ قصير جداً للأوصاف price VARCHAR(10) -- ❌ يجب أن يكون DECIMAL للمال );
نصيحة احترافية: لعناوين البريد الإلكتروني، VARCHAR(255) هو المعيار لأن الحد الأقصى لطول البريد الإلكتروني وفقاً لـ RFC 5321 هو 254 حرفاً.

أنواع التاريخ والوقت

يوفر MySQL عدة أنواع للبيانات الزمنية، كل منها بحالات استخدام محددة:

DATE - التاريخ فقط (بدون وقت) - التنسيق: YYYY-MM-DD - النطاق: 1000-01-01 إلى 9999-12-31 - التخزين: 3 بايت - استخدم لـ: تواريخ الميلاد، تواريخ النشر، المواعيد النهائية DATETIME - التاريخ والوقت - التنسيق: YYYY-MM-DD HH:MM:SS - النطاق: 1000-01-01 00:00:00 إلى 9999-12-31 23:59:59 - التخزين: 5-8 بايت - لا وعي بالمنطقة الزمنية - استخدم لـ: طوابع زمنية للأحداث، أوقات مجدولة TIMESTAMP - طابع زمني Unix - التنسيق: YYYY-MM-DD HH:MM:SS - النطاق: 1970-01-01 00:00:01 إلى 2038-01-19 03:14:07 - التخزين: 4 بايت - يحدّث تلقائياً عند تغيير الصف - واعٍ بالمنطقة الزمنية (يحول إلى UTC) - استخدم لـ: created_at، updated_at، last_login TIME - الوقت فقط (بدون تاريخ) - التنسيق: HH:MM:SS - النطاق: -838:59:59 إلى 838:59:59 - استخدم لـ: المدة، وقت اليوم، ساعات العمل YEAR - السنة فقط - التنسيق: YYYY - النطاق: 1901 إلى 2155 - التخزين: 1 بايت - استخدم لـ: سنة التصنيع، سنة التخرج

أفضل ممارسات التاريخ/الوقت

النمط القياسي: CREATE TABLE posts ( id INT PRIMARY KEY, title VARCHAR(200), content TEXT, published_date DATE, -- ✓ التاريخ فقط created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, -- ✓ تعيين تلقائي عند الإدراج updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP -- ✓ تحديث تلقائي عند التغيير ); CREATE TABLE events ( id INT PRIMARY KEY, event_name VARCHAR(100), event_datetime DATETIME, -- ✓ تاريخ ووقت محددان duration TIME, -- ✓ طول الحدث (مثلاً "02:30:00") created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE users ( id INT PRIMARY KEY, birth_date DATE, -- ✓ لا حاجة للوقت registered_at TIMESTAMP, -- ✓ وقت التسجيل الدقيق last_login TIMESTAMP -- ✓ تتبع آخر نشاط ); TIMESTAMP مقابل DATETIME: - استخدم TIMESTAMP لـ: created_at، updated_at (تحديث تلقائي) - استخدم DATETIME لـ: أحداث مجدولة، مواعيد (بدون تحديث تلقائي) - استخدم DATE لـ: تواريخ الميلاد، المواعيد النهائية (بدون مكون وقت)
مهم: TIMESTAMP لديه مشكلة 2038 (حد 32 بت). للتواريخ بعد 2038، استخدم DATETIME. MySQL 8.0+ يوسع دعم TIMESTAMP، لكن DATETIME أكثر أماناً للتواريخ البعيدة في المستقبل.

أنواع ENUM و SET

ENUM و SET تخزن مجموعات محددة مسبقاً من القيم:

ENUM - اختر قيمة واحدة من قائمة - التخزين: 1-2 بايت (مخزن كعدد صحيح داخلياً) - مثال: ENUM('draft', 'published', 'archived') - استخدم لـ: حقول الحالة بخيارات ثابتة CREATE TABLE posts ( id INT PRIMARY KEY, title VARCHAR(200), status ENUM('draft', 'published', 'archived') DEFAULT 'draft', priority ENUM('low', 'medium', 'high') DEFAULT 'medium' ); -- أمثلة الاستعلام SELECT * FROM posts WHERE status = 'published'; UPDATE posts SET status = 'archived' WHERE id = 1; SET - اختر قيم متعددة من قائمة - التخزين: 1-8 بايت حسب عدد القيم - مثال: SET('email', 'sms', 'push') - استخدم لـ: اختيارات متعددة، أذونات، أعلام CREATE TABLE users ( id INT PRIMARY KEY, name VARCHAR(100), notifications SET('email', 'sms', 'push', 'newsletter') DEFAULT 'email' ); INSERT INTO users VALUES (1, 'John', 'email,sms,push'); -- أمثلة الاستعلام SELECT * FROM users WHERE FIND_IN_SET('email', notifications);
قيود ENUM: إضافة أو إزالة القيم يتطلب ALTER TABLE. للخيارات المتغيرة بشكل متكرر، اعتبر جدول بحث بدلاً من ذلك. ENUM أفضل للقوائم الثابتة حقاً (مثل رموز الحالة).

نوع بيانات JSON (MySQL 5.7+)

نوع JSON الأصلي في MySQL يخزن ويتحقق من مستندات JSON:

فوائد نوع JSON: - التحقق التلقائي (يرفض JSON غير صالح) - تخزين فعال (تنسيق ثنائي) - وصول سريع بدوال JSON - مخطط مرن للبيانات المتغيرة مثال الاستخدام: CREATE TABLE products ( id INT PRIMARY KEY, name VARCHAR(200), attributes JSON -- تخزين سمات المنتج المرنة ); INSERT INTO products VALUES ( 1, 'Laptop', '{"brand": "Dell", "ram": "16GB", "storage": "512GB SSD", "color": "Silver"}' ); -- الاستعلام عن بيانات JSON SELECT name, JSON_EXTRACT(attributes, '$.brand') as brand, JSON_EXTRACT(attributes, '$.ram') as ram FROM products; -- صيغة أقصر (عامل ->) SELECT name, attributes->'$.brand' as brand FROM products; -- تحديث حقل JSON UPDATE products SET attributes = JSON_SET(attributes, '$.color', 'Black') WHERE id = 1; متى تستخدم JSON: ✓ سمات مرنة (مواصفات المنتج، إعدادات المستخدم) ✓ بنية متفاوتة عبر الصفوف ✓ تخزين استجابة API ✓ بيانات التكوين متى لا تستخدم JSON: ❌ الحقول المستعلم عنها بشكل متكرر (استخدم أعمدة عادية) ❌ البيانات التي تتطلب فهارس معقدة ❌ البيانات المنظمة بصرامة (طبّع بدلاً من ذلك)

DECIMAL مقابل FLOAT مقابل DOUBLE

DECIMAL(M,D) - دقة تامة - M = إجمالي الأرقام، D = أرقام بعد العلامة العشرية - مثال: DECIMAL(10,2) يخزن 12345678.90 - لا أخطاء تقريب - استخدم لـ: المال، الأسعار، الكميات التي تتطلب الدقة FLOAT - تقريبي (4 بايت) - الدقة: ~7 أرقام عشرية - استخدم لـ: قياسات علمية، عشريات غير حرجة DOUBLE - تقريبي (8 بايت) - الدقة: ~15 رقم عشري - استخدم لـ: حسابات علمية، إحداثيات للمال - استخدم دائماً DECIMAL: CREATE TABLE orders ( id INT PRIMARY KEY, subtotal DECIMAL(10,2), -- ✓ دقيق: $99,999,999.99 كحد أقصى tax DECIMAL(10,2), total DECIMAL(10,2), discount_percent DECIMAL(5,2) -- ✓ 0.00 إلى 100.00 ); -- أو التخزين كأعداد صحيحة (سنتات) CREATE TABLE orders_alt ( id INT PRIMARY KEY, total_cents BIGINT -- ✓ $21,474,836.47 كحد أقصى (إذا كنت تستخدم INT) );

تمرين تطبيقي:

أصلح مشاكل نوع البيانات في هذا الجدول:

CREATE TABLE employees_bad ( id TINYINT PRIMARY KEY, name VARCHAR(10), email TEXT, age VARCHAR(5), salary FLOAT, hire_date VARCHAR(50), is_active VARCHAR(10), department VARCHAR(255) );

النسخة المحسنة:

CREATE TABLE employees ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, -- ✓ دعم أكثر من 127 موظف name VARCHAR(100), -- ✓ أسماء أطول email VARCHAR(255) UNIQUE, -- ✓ طول البريد الإلكتروني القياسي age TINYINT UNSIGNED, -- ✓ نوع رقمي، 0-255 salary DECIMAL(10,2), -- ✓ دقة تامة للمال hire_date DATE, -- ✓ نوع تاريخ صحيح is_active BOOLEAN DEFAULT TRUE, -- ✓ TINYINT(1) لـ صحيح/خطأ department ENUM('HR','IT','Sales','Finance'), -- ✓ قائمة ثابتة من الأقسام created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP );

نصائح تحسين التخزين

1. استخدم UNSIGNED للقيم غير السالبة INT UNSIGNED يخزن 0 إلى 4.2 مليار (مقابل -2.1B إلى 2.1B) 2. تجنب VARCHAR(255) في كل مكان حلل طول البيانات الفعلي واختر بشكل مناسب 3. استخدم ENUM للقوائم الثابتة ENUM('yes','no') يستخدم 1 بايت مقابل VARCHAR(3) 4. تخزين المنطقيات كـ TINYINT(1) أو BOOLEAN أكثر كفاءة من VARCHAR('true'/'false') 5. استخدم أنواع التواريخ المناسبة DATE (3 بايت) مقابل DATETIME (8 بايت) مقابل VARCHAR(20) 6. اعتبر CHAR للبيانات ذات الطول الثابت CHAR(2) لرموز البلدان، CHAR(32) لتجزئات MD5

الملخص

في هذا الدرس، تعلمت:

  • اختر أصغر نوع بيانات يحتفظ ببياناتك بشكل موثوق
  • INT لمعظم المعرفات، BIGINT للحجم الكبير أو الطوابع الزمنية بالميلي ثانية
  • VARCHAR للنص المتغير، CHAR للطول الثابت، TEXT للمحتوى الكبير
  • TIMESTAMP لـ created_at/updated_at، DATETIME للأحداث، DATE لتواريخ الميلاد
  • ENUM للقوائم الثابتة، JSON للسمات المرنة
  • DECIMAL للمال (أبداً FLOAT)، تخزين السنتات كـ BIGINT بديل
  • استخدم UNSIGNED للقيم غير السالبة لمضاعفة النطاق الموجب
التالي: في الدرس التالي، سنستكشف أفضل ممارسات تصميم قواعد البيانات وأنماط كاملة لتطبيقات العالم الحقيقي!

ES
Edrees Salih
منذ 12 ساعة

We are still cooking the magic in the way!