DevOpsMar 28, 2026
Deep EVM #25: تقسيم جداول PostgreSQL — عندما يتجاوز جدولك 10 مليون صف
OS
Open Soft Team
Engineering Team
متى تحتاج التقسيم
عندما يتجاوز جدول 10-100 مليون صف، تبدأ المشاكل:
- الفهارس تنمو وتبطئ
- VACUUM يستغرق وقتاً أطول
- النسخ الاحتياطي يصبح بطيئاً
- الاستعلامات تتدهور تدريجياً
التقسيم يحل هذا بتقسيم الجدول إلى أجزاء أصغر وأكثر قابلية للإدارة.
أنواع التقسيم
تقسيم بالنطاق (Range)
CREATE TABLE transactions (
id UUID DEFAULT gen_random_uuid(),
amount NUMERIC NOT NULL,
created_at TIMESTAMPTZ NOT NULL
) PARTITION BY RANGE (created_at);
CREATE TABLE transactions_2024_01 PARTITION OF transactions
FOR VALUES FROM ('2024-01-01') TO ('2024-02-01');
CREATE TABLE transactions_2024_02 PARTITION OF transactions
FOR VALUES FROM ('2024-02-01') TO ('2024-03-01');
تقسيم بالقائمة (List)
CREATE TABLE articles (
id UUID DEFAULT gen_random_uuid(),
locale VARCHAR(5) NOT NULL,
title TEXT NOT NULL
) PARTITION BY LIST (locale);
CREATE TABLE articles_en PARTITION OF articles FOR VALUES IN ('en');
CREATE TABLE articles_ar PARTITION OF articles FOR VALUES IN ('ar');
CREATE TABLE articles_ru PARTITION OF articles FOR VALUES IN ('ru');
تقسيم بالتجزئة (Hash)
CREATE TABLE events (
id UUID DEFAULT gen_random_uuid(),
user_id UUID NOT NULL,
data JSONB
) PARTITION BY HASH (user_id);
CREATE TABLE events_0 PARTITION OF events FOR VALUES WITH (MODULUS 4, REMAINDER 0);
CREATE TABLE events_1 PARTITION OF events FOR VALUES WITH (MODULUS 4, REMAINDER 1);
الصيانة التلقائية
-- إنشاء أقسام مستقبلية تلقائياً
CREATE OR REPLACE FUNCTION create_monthly_partition()
RETURNS void AS $$
DECLARE
next_month DATE := date_trunc('month', NOW() + interval '1 month');
partition_name TEXT;
BEGIN
partition_name := 'transactions_' || to_char(next_month, 'YYYY_MM');
EXECUTE format(
'CREATE TABLE IF NOT EXISTS %I PARTITION OF transactions FOR VALUES FROM (%L) TO (%L)',
partition_name, next_month, next_month + interval '1 month'
);
END;
$$ LANGUAGE plpgsql;
تأثير الأداء
| العملية | بدون تقسيم (100M صف) | مع تقسيم (12 قسم) |
|---|---|---|
| SELECT بتاريخ | 2,500ms | 50ms |
| INSERT | 5ms | 3ms |
| VACUUM | 45 دقيقة | 4 دقائق |
| حذف بيانات قديمة | 30 دقيقة | فوري (DROP PARTITION) |
الخلاصة
تقسيم الجداول ضروري عندما تنمو البيانات. اختر النوع المناسب: بالنطاق للبيانات الزمنية، بالقائمة للفئات، بالتجزئة للتوزيع المتساوي.