يعتمد ClickHouse Managed Postgres على PostgreSQL القياسي، ويتكامل مع منظومة PostgreSQL الحالية. وبالنسبة إلى معظم مهام التطوير، يمكنك التطوير والاختبار بالاعتماد على مثيل PostgreSQL محلي يعمل داخل Docker بدلًا من النشر على السحابة.
يوفّر هذا النهج دورة ملاحظات سريعة، ويُبسّط عملية الإعداد، ويقلّل الاعتماد على البنية التحتية المشتركة، ويتيح لك التجربة بأمان من دون التأثير في أنظمة الإنتاج.
ليس الهدف هو محاكاة بيئة الإنتاج بدقة تامة. بدلًا من ذلك، أنشئ بيئة محلية قابلة لإعادة الإنتاج بحيث:
- تستخدم الإصدار الرئيسي نفسه من PostgreSQL المستخدم في الإنتاج.
- تطبّق تعريفات المخطط نفسها المستخدمة في الإنتاج.
- تحتوي على بيانات تطوير ممثّلة.
- تدعم سير عمل تطوير التطبيقات واختبارها بشكل طبيعي.
وبما أن ClickHouse Managed Postgres يستند إلى PostgreSQL القياسي، فإن أطر الترحيل الحالية، وأدوات إدارة المخطط، وأساليب تهيئة البيانات تعمل من دون أي تعديل.
مثال على سير العمل في التطوير
يكون سير العمل المعتاد للتطوير المحلي على النحو التالي:
graph LR
A[Apply the application<br/>schema] --> B[Local PostgreSQL in Docker] --> C[Apply schema]
graph LR
A[Restore sanitized tenant<br/>dataset] -.-> B[Generate seed data] -.-> C[Develop and test locally]
ينسجم ClickHouse Managed Postgres مع سير عمل تطوير PostgreSQL الحالية. ومن خلال التطوير باستخدام مثيل PostgreSQL محلي، يمكن للفرق إجراء التعديلات بسرعة، والحفاظ على بيئات قابلة لإعادة الإنشاء، واكتساب الثقة بأن التطبيقات ستعمل بشكل متسق عند نشرها على ClickHouse Managed Postgres.
شغّل PostgreSQL محليًا باستخدام Docker
أسهل طريقة لإنشاء بيئة تطوير محلية هي تشغيل PostgreSQL داخل Docker.
اختر إصدار PostgreSQL الذي يطابق نشر ClickHouse Managed Postgres لديك:
services:
postgres:
image: postgres:18
container_name: local-postgres
restart: unless-stopped
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: app
ports:
- "15432:5432"
volumes:
- postgres_data:/var/lib/postgresql
volumes:
postgres_data:ابدأ تشغيل PostgreSQL:
docker compose up -dتحقّق من إمكانية الاتصال:
psql -h localhost -U postgres -p 15432 -d appفي هذه المرحلة، يعمل PostgreSQL محليًا، لكنه لا يتضمن بعد مخطط بيانات التطبيق أو أي بيانات خاصة ببيئة التطوير.
تطبيق مخطط بيانات التطبيق
لا توجد طريقة موحّدة إلزامية لإنشاء المخطط في بيئة محلية. لدى معظم المؤسسات بالفعل سير عمل راسخ لإدارة المخطط يمكن إعادة استخدامه كما هو.
ترحيلات التطبيق
تستخدم فرق كثيرة إطار الترحيل نفسه الذي يعمل في بيئتَي ما قبل الإنتاج والإنتاج — مثل أدوات Flyway وLiquibase وRails migrations وDjango migrations وPrisma migrations وAlembic.
يضمن تطبيق الترحيلات محليًا اختبار تطور المخطط باستمرار ضمن سير التطوير المعتاد:
./migrate up
# or
npm run migrate
# or
rails db:migrateتفريغات PostgreSQL الخاصة بالمخطط فقط
يمكن لتصدير PostgreSQL الخاص بالمخطط فقط إعادة إنشاء بنية قاعدة بيانات موجودة. ويكون ذلك مفيدًا في الإعداد الموجّه، وفهم سلوك المخطط، والتحقق من التوافق، أو الإعداد السريع الأولي لبيئات التطوير.
صدّر المخطط:
pg_dump \
--schema-only \
--no-owner \
--no-privileges \
-h <host> \
-U <user> \
-d <database> \
> schema.sqlاستعد محليًا:
psql \
-h localhost \
-U postgres \
-p 15432 \
-d app \
-f schema.sqlتعريفات SQL المحفوظة في المستودع
تحتفظ بعض الفرق بتعريفات المخطط مباشرةً ضمن نظام التحكم في الإصدارات على شكل ملفات SQL. ويمكن تطبيق هذه الملفات مباشرةً على مثيل PostgreSQL محلي أثناء إعداد البيئة.
وبصرف النظر عن النهج المتّبع، فالنتيجة الأهم هي أن إنشاء المخطط يتم تلقائيًا، ويمكن إعادة إنتاجه، ويستند إلى تعريفات خاضعة للتحكم في الإصدارات.
ملء بيانات تطويرية تمثيلية
بمجرد إنشاء المخطط، املأ قاعدة البيانات ببيانات تطويرية تمثيلية.
في معظم سير عمل التطوير، تكون مجموعات البيانات الاصطناعية التي تُنشأ بواسطة برامج نصية أولية كافية. إذ يسهل إعادة إنشائها، وهي آمنة للتوزيع، كما أنها تتجنب اعتبارات الامتثال والأمان المرتبطة ببيانات بيئة الإنتاج.
ومن الأساليب الشائعة في تطبيقات SaaS إنشاء بيانات لعدد صغير من المستأجرين النموذجيين، وبناء علاقات واقعية بين المستخدمين والمنتجات والطلبات وغيرها من كيانات الأعمال.
مثال على مخطط متعدد المستأجرين
يوضح المخطط التالي تطبيق SaaS مبسطًا متعدد المستأجرين:
CREATE TABLE tenants (
id UUID PRIMARY KEY,
name TEXT NOT NULL
);
CREATE TABLE users (
id UUID PRIMARY KEY,
tenant_id UUID NOT NULL REFERENCES tenants(id),
email TEXT NOT NULL,
first_name TEXT,
last_name TEXT,
created_at TIMESTAMP DEFAULT now()
);
CREATE TABLE products (
id UUID PRIMARY KEY,
tenant_id UUID NOT NULL REFERENCES tenants(id),
name TEXT NOT NULL,
price NUMERIC(10,2)
);
CREATE TABLE orders (
id UUID PRIMARY KEY,
tenant_id UUID NOT NULL REFERENCES tenants(id),
user_id UUID NOT NULL REFERENCES users(id),
status TEXT,
created_at TIMESTAMP DEFAULT now()
);
CREATE TABLE order_items (
id UUID PRIMARY KEY,
order_id UUID NOT NULL REFERENCES orders(id),
product_id UUID NOT NULL REFERENCES products(id),
quantity INTEGER
);
CREATE TABLE audit_logs (
id UUID PRIMARY KEY,
tenant_id UUID NOT NULL REFERENCES tenants(id),
entity_type TEXT,
entity_id UUID,
action TEXT,
created_at TIMESTAMP DEFAULT now()
);إنشاء بيانات تجريبية
ثبّت التبعيات:
pip install faker psycopg2-binaryأنشئ ملفًا باسم seed.py:
import random
import uuid
import psycopg2
from faker import Faker
fake = Faker()
conn = psycopg2.connect(
host="localhost",
port=15432,
dbname="app",
user="postgres",
password="postgres"
)
cur = conn.cursor()
tenant_ids = []
for tenant_name in [
"Tenant A",
"Tenant B",
"Tenant C"
]:
tenant_id = str(uuid.uuid4())
tenant_ids.append(tenant_id)
cur.execute(
"""
INSERT INTO tenants(id, name)
VALUES (%s, %s)
""",
(tenant_id, tenant_name)
)
for tenant_id in tenant_ids:
users = []
products = []
for _ in range(20):
user_id = str(uuid.uuid4())
users.append(user_id)
cur.execute(
"""
INSERT INTO users(
id,
tenant_id,
email,
first_name,
last_name
)
VALUES (%s,%s,%s,%s,%s)
""",
(
user_id,
tenant_id,
fake.email(),
fake.first_name(),
fake.last_name()
)
)
for _ in range(15):
product_id = str(uuid.uuid4())
products.append(product_id)
cur.execute(
"""
INSERT INTO products(
id,
tenant_id,
name,
price
)
VALUES (%s,%s,%s,%s)
""",
(
product_id,
tenant_id,
fake.word(),
round(random.uniform(10, 500), 2)
)
)
for _ in range(50):
order_id = str(uuid.uuid4())
cur.execute(
"""
INSERT INTO orders(
id,
tenant_id,
user_id,
status
)
VALUES (%s,%s,%s,%s)
""",
(
order_id,
tenant_id,
random.choice(users),
random.choice([
"pending",
"completed",
"cancelled"
])
)
)
for _ in range(random.randint(1, 5)):
cur.execute(
"""
INSERT INTO order_items(
id,
order_id,
product_id,
quantity
)
VALUES (%s,%s,%s,%s)
""",
(
str(uuid.uuid4()),
order_id,
random.choice(products),
random.randint(1, 10)
)
)
cur.execute(
"""
INSERT INTO audit_logs(
id,
tenant_id,
entity_type,
entity_id,
action
)
VALUES (%s,%s,%s,%s,%s)
""",
(
str(uuid.uuid4()),
tenant_id,
"order",
order_id,
"created"
)
)
conn.commit()
conn.close()نفِّذ البرنامج النصي:
python seed.pyتحتوي مجموعة البيانات الناتجة على:
| الجدول | السجلات |
|---|---|
| tenants | 3 |
| users | 60 |
| products | 45 |
| orders | 150 |
| order_items | 400+ |
| audit_logs | 150+ |
هذه المجموعة من البيانات كبيرة بما يكفي لتجربة سير عمل التطبيقات الشائعة، ومنطق عزل المستأجرين، واستعلامات التقارير، وفحوصات سلامة العلاقات، مع بقائها خفيفة بما يكفي للتطوير والاختبار محليًا.
بيئة تطوير PostgreSQL + ClickHouse
تركّز الأمثلة أعلاه على تطوير PostgreSQL محليًا. إذا كنت تريد اختبار معمارية PostgreSQL-to-ClickHouse الكاملة محليًا، يمكنك تشغيل مكدس PostgreSQL + ClickHouse مفتوح المصدر.
يجمع هذا المكدس بين PostgreSQL لأحمال عمل المعاملات، وClickHouse للتحليلات، وPeerDB لالتقاط بيانات التغيير (CDC) الأصلي. ويتيح لك التطوير على PostgreSQL مع تكرار البيانات باستمرار إلى ClickHouse، مما يتيح اختبار التحليلات التشغيلية، وأحمال عمل التقارير، ومسارات البيانات الآنية مباشرةً من حاسوبك المحمول.
يمكن تشغيل هذا المكدس بأمر واحد، وهو يتضمن جميع الخدمات المطلوبة معدّة مسبقًا:
git clone https://github.com/ClickHouse/postgres-clickhouse-stack.git
cd postgres-clickhouse-stack
./run.sh startيتضمن المكدس:
- PostgreSQL
- ClickHouse
- PeerDB لالتقاط بيانات التغيير (CDC) في PostgreSQL
- خدمات مساندة وتطبيقات تجريبية
للحصول على إرشادات الإعداد، وتفاصيل المعمارية، وشرح عملي للمكدس الكامل، راجع:
تُعد هذه خطوة تالية مفيدة بعد تشغيل تطبيقك محليًا على PostgreSQL، وعندما تريد التحقق من المزامنة من PostgreSQL إلى ClickHouse، والتحليلات في الوقت الفعلي، وسلوك التطبيق من طرف إلى طرف.