توسيع قاعدة البيانات: Vertical vs Horizontal

Vertical = أضف RAM. Horizontal = أضف سيرفرات. Replication، sharding، read replicas — نشرح كل خيار ومتى تستخدمه.
مقدمة
عندما تنمو قاعدة مستخدميك وتزداد بياناتك، ستصل حتماً إلى نقطة تبدأ فيها قاعدة البيانات بالتباطؤ. توسيع قواعد البيانات (Database Scaling) هو أحد أهم القرارات التقنية التي تواجهها أي تطبيق ناجح. هذا الدليل يشرح الخيارات المتاحة وكيف تختار الأنسب لحالتك.
أنواع التوسيع
Vertical Scaling (توسيع عمودي)
الطريقة الأبسط: رفع مواصفات السيرفر الحالي (CPU، RAM، SSD أسرع).
المزايا:
- لا تغيير في الكود
- سريع في التنفيذ
- بسيط في الإدارة
العيوب:
- له حد أقصى
- قد يتطلب downtime
- مكلف عند المستويات العالية
متى تستخدمه: الخيار الأول دائماً. على كلاود (cloud.net.sa) يمكنك رفع مواصفات VPS في دقائق.
Horizontal Scaling (توسيع أفقي)
إضافة سيرفرات متعددة تعمل معاً.
المزايا:
- توسع غير محدود نظرياً
- لا نقطة فشل واحدة
- مناسب للأحجام الكبيرة جداً
العيوب:
- يتطلب تعديل في الكود
- أعقد في الإدارة
- يحتاج خبرة في distributed systems
خيارات عملية للتوسيع
1. Read Replicas
إضافة سيرفرات قراءة تأخذ نسخة من قاعدة البيانات الرئيسية.
-- على MySQL، إعداد Master-Slave Replication
-- على السيرفر الرئيسي (Master)
CHANGE MASTER TO
MASTER_HOST='replica-server-ip',
MASTER_USER='replication_user',
MASTER_PASSWORD='strong_password';
// في Laravel، توجيه القراءة للـ replica
// config/database.php
'mysql' => [
'read' => [
'host' => ['replica1-ip', 'replica2-ip'],
],
'write' => [
'host' => ['master-ip'],
],
'driver' => 'mysql',
// ...
],
مناسب لـ: التطبيقات التي 80%+ من عملياتها قراءة (عرض بيانات، تقارير).
2. Connection Pooling
تجميع الاتصالات بدل فتح اتصال جديد لكل طلب.
# تثبيت PgBouncer لـ PostgreSQL
apt install pgbouncer
# أو ProxySQL لـ MySQL
apt install proxysql
# /etc/pgbouncer/pgbouncer.ini
[databases]
myapp = host=127.0.0.1 port=5432 dbname=myapp
[pgbouncer]
pool_mode = transaction
max_client_conn = 1000
default_pool_size = 100
هذا وحده يحل مشكلة "Too many connections" في كثير من الحالات.
3. Database Caching مع Redis
تخفيف الضغط على قاعدة البيانات بتخزين نتائج الاستعلامات الشائعة.
# تثبيت Redis
apt install redis-server
systemctl enable redis-server
// Laravel: استخدام cache للاستعلامات المتكررة
$users = Cache::remember('active_users', 3600, function {
return User::where('active', true)->get;
});
// للبيانات التي تتغير نادراً
$settings = Cache::rememberForever('app_settings', function {
return Setting::all->keyBy('key');
});
4. Database Sharding
تقسيم البيانات على قواعد بيانات متعددة حسب معيار معين.
// مثال: تقسيم حسب المنطقة الجغرافية
function getConnection(string $region): Connection {
return match($region) {
'riyadh' => DB::connection('db_riyadh'),
'jeddah' => DB::connection('db_jeddah'),
default => DB::connection('db_main'),
};
}
تحذير: Sharding معقد جداً في التنفيذ والصيانة. لا تلجأ إليه إلا بعد استنفاد الخيارات الأبسط.
جدول المقارنة
| الحل | التعقيد | التكلفة | الأثر |
|---|---|---|---|
| Vertical Scaling | منخفض | متوسط | فوري |
| Read Replicas | متوسط | متوسط | عالي للقراءة |
| Connection Pooling | منخفض | منخفضة | عالي |
| Redis Caching | منخفض | منخفضة | عالي جداً |
| Sharding | عالي جداً | عالية | لأحجام ضخمة |
مؤشرات تحتاج توسيعاً
- زمن الاستجابة > 200ms باستمرار
- CPU قاعدة البيانات > 70% باستمرار
- "Too many connections" في السجلات
- Deadlocks متكررة
- القرص الصلب يقترب من 80%
التشخيص قبل التوسيع
# عرض الاستعلامات البطيئة في MySQL
mysql -u root -p << 'SQL'
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 1;
SET GLOBAL slow_query_log_file = '/var/log/mysql/slow.log';
SQL
# تحليل استعلام بطيء
EXPLAIN SELECT * FROM orders WHERE user_id = 123 AND status = 'pending';
إضافة index مناسب قد تحل المشكلة كلها:
CREATE INDEX idx_orders_user_status ON orders(user_id, status);
توصية عملية
الترتيب الصحيح لحل مشاكل أداء قاعدة البيانات:
- أضف الـ indexes الناقصة — مجاني وفوري
- فعّل Redis caching — تخفيض 80% من الاستعلامات المتكررة
- رفع مواصفات السيرفر — مع كلاود هذا سهل وسريع
- أضف Read Replica — إذا كان التطبيق يعتمد على القراءة الكثيفة
- Connection Pooling — إذا كان عدد الاتصالات المشكلة
- Sharding — فقط عند الملايين من المستخدمين
خلاصة
لا تقفز مباشرة إلى الحلول المعقدة. في أغلب الحالات، إضافة index أو تفعيل Redis يحل المشكلة. التوسيع الأفقي والـ sharding للمراحل المتقدمة جداً. ابدأ بالبسيط وقِس الأثر قبل الانتقال للخطوة التالية.


