PostgreSQL: طرق العرض وطرق العرض المادية في PostgreSQL

آخر تحديث: 2026-08-26

1. ما ستتعلمه


2. القصة

Alice هي مهندسة بيانات في منصة تجارة إلكترونية. فريق العمليات يراجع تقرير ملخص المبيعات كل يوم في الساعة 8:00، والذي يضم 5 جداول، ويجمع 3 ملايين سجل طلب، ويستغرق ساعتين للاستعلام.

قال رئيسها: "هل يمكن أن يعود التقرير فورياً؟"

عرّفت Alice الاستعلام كـ طريقة عرض مادية، تُحدث تلقائياً كل يوم في الساعة 4:00 صباحاً. استعلام التقرير المحسوب مسبقاً انخفض من ساعتين إلى 3 ثوانٍ. لكن بيانات طريقة العرض المادية ليست فورية — هذه هي المقايضة بين طرق العرض العادية وطرق العرض المادية.


3. المفهوم: طرق العرض العادية

(1) صيغة CREATE VIEW

SQL
CREATE [OR REPLACE] VIEW view_name [(column_aliases)] AS
  SELECT ...;

طريقة العرض هي تعريف استعلام مخزن — لا تخزن بيانات. كل مرة تستعلم طريقة عرض، تقوم PostgreSQL بتوسيع (إعادة كتابة) تعريف طريقة العرض إلى الاستعلام الأساسي وتنفيذه.

الخاصية الوصف
ما يُخزن نص الاستعلام فقط
حداثة البيانات فورية، تعكس دائماً أحدث بيانات الجدول الأساسي
الأداء نفس تنفيذ الاستعلام الأساسي مباشرة
المساحة المستخدمة لا شيء تقريباً

(1) ▶ مثال

SQL
CREATE VIEW v_daily_sales AS
SELECT
  order_date,
  region,
  COUNT(*)               AS order_count,
  SUM(amount)            AS total_revenue,
  AVG(amount)            AS avg_order_value
FROM orders
GROUP BY order_date, region;

Output:

TEXT 📖 للعرض فقط
 count 
-------
     5
(1 row)

(2) ▶ مثال

SQL
SELECT * FROM v_daily_sales
WHERE order_date >= '2025-01-01'
ORDER BY total_revenue DESC;

Output:

TEXT 📖 للعرض فقط
 id | name     | value 
----+----------+-------
  1 | example  | 42
(1 row)

مكافئ لكتابة SELECT الأساسي مباشرة — PostgreSQL توسعه تلقائياً.

(2) ALTER VIEW و DROP VIEW

العملية الصيغة الوصف
إعادة تسمية ALTER VIEW v RENAME TO v_new إعادة تسمية طريقة العرض
تعيين عمود افتراضي ALTER VIEW v ALTER COLUMN c SET DEFAULT d تغيير افتراضي عمود
تعيين المالك ALTER VIEW v OWNER TO role تغيير المالك
حذف DROP VIEW [IF EXISTS] v [CASCADE] CASCADE يحذف طرق العرض التابعة

(3) ▶ مثال

SQL
ALTER VIEW v_daily_sales RENAME TO v_daily_summary;

DROP VIEW IF EXISTS v_daily_summary CASCADE;

Output:

TEXT 📖 للعرض فقط
-- SQL statement executed successfully

(3) آلية توسيع طريقة العرض

100%
flowchart LR
    A["SELECT * FROM v_daily_sales"] --> B["إعادة كتابة<br/>توسيع تعريف طريقة العرض"]
    B --> C["SELECT order_date, region, COUNT(*)...<br/>FROM orders<br/>GROUP BY ..."]
    C --> D[المحسن]
    D --> E[تنفيذ]
    style B fill:#fff9c4
    style D fill:#c8e6c9

4. المفهوم: طرق العرض القابلة للتحديث

(1) أي طرق العرض قابلة للتحديث

في PostgreSQL، طرق العرض البسيطة التي تحقق جميع الشروط التالية قابلة للتحديث تلقائياً (تدعم INSERT / UPDATE / DELETE):

الشرط الوصف
FROM جدول أساسي واحد فقط لا JOIN
لا GROUP BY / HAVING لا تجميع
لا DISTINCT لا إزالة تكرار
لا دوال النوافذ لا OVER
أعمدة SELECT هي أعمدة الجدول الأساسي لا تعبيرات/أعمدة محسوبة

(4) ▶ مثال

SQL
CREATE VIEW v_active_users AS
SELECT user_id, name, email, status
FROM users
WHERE status = 'active';

Output:

TEXT 📖 للعرض فقط
CREATE TABLE
SQL
UPDATE v_active_users SET name = 'Alice Wang' WHERE user_id = 1;

DELETE FROM v_active_users WHERE user_id = 99;

INSERT INTO v_active_users (user_id, name, email, status)
VALUES (101, 'Charlie', 'charlie@example.com', 'active');

(2) WITH CHECK OPTION

الخيار السلوك
بدون CHECK OPTION الهروب مسموح؛ الصفوف المحدثة قد لا تعود تظهر في طريقة العرض
WITH CHECK OPTION الهروب ممنوع؛ الصفوف المحدثة يجب أن تظل تحقق شرط طريقة العرض
WITH CASCADED CHECK OPTION طريقة العرض الحالية + طرق العرض التابعة تُفحص (تكراري)
WITH LOCAL CHECK OPTION فقط شرط طريقة العرض الحالية يُفحص

(5) ▶ مثال

SQL
CREATE VIEW v_active_users_strict AS
SELECT user_id, name, email, status
FROM users
WHERE status = 'active'
WITH CHECK OPTION;
SQL
UPDATE v_active_users_strict SET status = 'inactive' WHERE user_id = 1;
TEXT 📖 للعرض فقط
ERROR: new row violates check option for view "v_active_users_strict"
DETAIL: Failing row contains (1, ..., inactive).

(6) ▶ مثال

SQL
INSERT INTO v_active_users (user_id, name, email, status)
VALUES (200, 'Bob', 'bob@example.com', 'active');

SELECT * FROM v_active_users WHERE user_id = 200;
TEXT 📖 للعرض فقط
 user_id | name |       email        | status
---------+------+--------------------+--------
     200 | Bob  | bob@example.com    | active

5. المفهوم: طرق العرض المادية

(1) نظرة عامة على MATERIALIZED VIEW

طريقة العرض المادية تخزن نتيجة الاستعلام فعلياً على القرص؛ الاستعلامات تقرأ البيانات المحسوبة مسبقاً مباشرة، بدون إعادة تنفيذ الاستعلام الأساسي. هذه ميزة خاصة بـ PostgreSQL.

الخاصية طريقة العرض العادية طريقة العرض المادية
ما يُخزن نص الاستعلام نص الاستعلام + بيانات النتيجة
حداثة البيانات فورية تُحدث فقط عند التحديث
أداء الاستعلام نفس الاستعلام الأساسي سريع جداً (يقرأ المحسوب مسبقاً)
المساحة المستخدمة لا شيء تقريباً نفس حجم مجموعة النتائج
قابلة للتحديث طرق العرض البسيطة يمكنها لا DML مباشر
طريقة التحديث غير مطلوبة REFRESH MATERIALIZED VIEW

(7) ▶ مثال

SQL
CREATE MATERIALIZED VIEW mv_monthly_sales AS
SELECT
  DATE_TRUNC('month', order_date)::date AS month,
  region,
  COUNT(*)    AS order_count,
  SUM(amount) AS total_revenue,
  AVG(amount) AS avg_order_value
FROM orders
GROUP BY DATE_TRUNC('month', order_date), region
WITH DATA;

Output:

TEXT 📖 للعرض فقط
 count 
-------
     5
(1 row)

(8) ▶ مثال

SQL
SELECT * FROM mv_monthly_sales
WHERE month >= '2025-01-01'
ORDER BY total_revenue DESC;

Output:

TEXT 📖 للعرض فقط
 id | name     | value 
----+----------+-------
  1 | example  | 42
(1 row)

يعيد بالمللي ثانية، لأن البيانات محسوبة مسبقاً ومخزنة.

(2) REFRESH

الصيغة السلوك القفل السرعة
REFRESH MATERIALIZED VIEW mv تحديث كامل، يستبدل جميع البيانات يأخذ قفلاً حصرياً، يحظر القراءة أبطأ
REFRESH MATERIALIZED VIEW CONCURRENTLY mv تحديث تزايدي (يحتاج فهرس فريد) لا يحظر القراءة أسرع

CONCURRENTLY هي ميزة خاصة بـ PostgreSQL: طريقة العرض تبقى قابلة للاستعلام أثناء التحديث — العمل لا يُحظر.

(9) ▶ مثال

SQL
REFRESH MATERIALIZED VIEW mv_monthly_sales;

Output:

TEXT 📖 للعرض فقط
-- SQL statement executed successfully

جميع SELECTs على طريقة العرض المادية هذه تُحظر أثناء التحديث.

(10) ▶ مثال

SQL
REFRESH MATERIALIZED VIEW CONCURRENTLY mv_monthly_sales;

Output:

TEXT 📖 للعرض فقط
-- SQL statement executed successfully

الشرط المسبق: طريقة العرض المادية يجب أن يكون لديها فهرس فريد واحد على الأقل.

SQL
CREATE UNIQUE INDEX idx_mv_monthly_sales_pk
  ON mv_monthly_sales (month, region);

REFRESH MATERIALIZED VIEW CONCURRENTLY mv_monthly_sales;

(3) WITH DATA مقابل WITH NO DATA

الخيار السلوك
WITH DATA ملء البيانات فوراً عند الإنشاء (افتراضي)
WITH NO DATA لا تملأ عند الإنشاء؛ يجب REFRESH قبل أول استعلام

(11) ▶ مثال

SQL
CREATE MATERIALIZED VIEW mv_expensive_report AS
SELECT ... FROM ... WITH NO DATA;

REFRESH MATERIALIZED VIEW mv_expensive_report;

Output:

TEXT 📖 للعرض فقط
CREATE TABLE

(12) ▶ مثال

SQL
SELECT cron.schedule(
  'refresh_monthly_sales',
  '0 4 * * *',
  $$REFRESH MATERIALIZED VIEW CONCURRENTLY mv_monthly_sales$$
);

Output:

TEXT 📖 للعرض فقط
 id | name     | value 
----+----------+-------
  1 | example  | 42
(1 row)

يُحدث تلقائياً كل يوم في الساعة 4:00 صباحاً.


6. طرق العرض مقابل طرق العرض المادية مقابل الجداول المؤقتة

البعد طريقة عرض عادية طريقة عرض مادية جدول مؤقت
يخزن تعريف الاستعلام نعم نعم لا
يخزن البيانات لا نعم نعم
حداثة البيانات فورية تحديث يدوي صيانة يدوية
أداء الاستعلام يعتمد على الاستعلام الأساسي سريع جداً سريع
استمرار عبر الجلسات نعم نعم لا (يختفي بعد الجلسة)
يدعم الفهارس لا (يستخدم فهارس الجدول الأساسي) نعم نعم
يدعم DML طرق العرض البسيطة قابلة للتحديث لا نعم
السيناريو النموذجي تبسيط الاستعلامات حساب مسبق للتقارير نتائج وسيطة مؤقتة
100%
classDiagram
    class View {
        +يخزن نص الاستعلام
        +بيانات فورية
        +طريقة عرض بسيطة قابلة لـ DML
        +WITH CHECK OPTION
    }
    class MaterializedView {
        +يخزن نص الاستعلام+البيانات
        +تحديث REFRESH
        +CONCURRENTLY
        +قابل للفهرسة
        +WITH DATA/NO DATA
    }
    class TempTable {
        +يخزن البيانات فقط
        +يختفي بعد الجلسة
        +DML كامل
        +قابل للفهرسة
    }
    View <|-- MaterializedView : extends
    MaterializedView ..|> TempTable : أداء مشابه

7. أفضل ممارسات إدارة طرق العرض

(1) اصطلاحات التسمية

النوع البادئة الموصى بها مثال
طريقة عرض عادية v_ v_active_users
طريقة عرض مادية mv_ mv_monthly_sales
جدول مؤقت tmp_ tmp_import_data

(2) تبعيات طرق العرض والأمان

العملية الخطر الحل
حذف الجدول الأساسي تصبح طريقة العرض غير صالحة DROP TABLE CASCADE يحذف تلقائياً طرق العرض التابعة
تعديل عمود الجدول الأساسي قد تخطئ طريقة العرض حدث التعريف بـ CREATE OR REPLACE VIEW
التحكم في الصلاحيات طريقة العرض يمكنها تحديد رؤية الأعمدة GRANT SELECT ON view TO role

(13) ▶ مثال

SQL
CREATE VIEW v_user_public AS
SELECT user_id, name
FROM users;

GRANT SELECT ON v_user_public TO reporter_role;

REVOKE SELECT ON users FROM reporter_role;

Output:

TEXT 📖 للعرض فقط
CREATE TABLE

reporter_role يمكنه فقط رؤية user_id و name، ليس الأعمدة الحساسة مثل email.


8. مثال شامل

SQL
CREATE MATERIALIZED VIEW mv_sales_report AS
SELECT
  DATE_TRUNC('month', o.order_date)::date AS month,
  p.category,
  o.region,
  COUNT(*)                                AS order_count,
  COUNT(DISTINCT o.customer_id)           AS unique_customers,
  SUM(o.amount)                           AS total_revenue,
  SUM(o.amount) FILTER (WHERE o.amount >= 50000) AS big_deal_revenue,
  AVG(o.amount)                           AS avg_order_value,
  SUM(oi.quantity * oi.unit_price)        AS total_gmv
FROM orders o
JOIN order_items oi ON o.order_id = oi.order_id
JOIN products p ON oi.product_id = p.product_id
GROUP BY DATE_TRUNC('month', o.order_date), p.category, o.region
WITH DATA;

CREATE UNIQUE INDEX idx_mv_sales_report_pk
  ON mv_sales_report (month, category, region);

CREATE VIEW v_sales_dashboard AS
SELECT
  month,
  region,
  SUM(total_revenue)  AS region_revenue,
  SUM(order_count)    AS region_orders,
  SUM(unique_customers) AS region_customers
FROM mv_sales_report
GROUP BY month, region;

REFRESH MATERIALIZED VIEW CONCURRENTLY mv_sales_report;

9. تدفق التنفيذ

تدفق إنشاء وتحديث طريقة العرض المادية:

100%
flowchart TD
    A[CREATE MATERIALIZED VIEW] --> B[تنفيذ الاستعلام الأساسي]
    B --> C[كتابة النتائج على القرص]
    C --> D[يمكن إنشاء فهارس]
    D --> E[الاستعلام يقرأ بيانات القرص مباشرة]
    E --> F{بحاجة لتحديث؟}
    F -->|REFRESH| G[إعادة تنفيذ الاستعلام الأساسي]
    G --> H[استبدال البيانات القديمة]
    H --> E
    F -->|CONCURRENTLY| I[تحديث تزايدي بالمقارنة]
    I --> J[لا يحظر القراءة]
    J --> E

    style A fill:#e1f5fe
    style E fill:#c8e6c9
    style I fill:#fff9c4
الخطوة الوصف
إنشاء تنفيذ الاستعلام الأساسي، استمرار النتيجة على القرص
استعلام قراءة بيانات القرص مباشرة، لا استعلام أساسي منفذ
تحديث إعادة تنفيذ الاستعلام الأساسي، استبدال البيانات القديمة
CONCURRENTLY تحديث تزايدي، لا يحظر الاستعلامات أثناء التحديث

❓ أسئلة شائعة

...


📖 ملخص


📝 تمارين

  1. تمرين أساسي
  2. تمرين متوسط
  3. تمرين صعب

ملخص

س هل تؤثر طرق العرض العادية على الأداء؟
ج لا. طريقة العرض هي مجرد إعادة كتابة استعلام — الأداء مطابق لكتابة SQL الأساسي مباشرة. طريقة العرض المعقدة لا تضيف عبئاً إضافياً.
س لماذا لا أجد البيانات المدرجة بعد الإدراج عبر طريقة عرض؟
ج الصف المدرج قد لا يحقق شرط WHERE لطريقة العرض. استخدم WITH CHECK OPTION لمنع هذا.
س لماذا يحتاج تحديث CONCURRENTLY إلى فهرس فريد؟
ج CONCURRENTLY يقوم بتحديث تزايدي بمقارنة البيانات القديمة والجديدة؛ الفهرس الفريد يعرف كل صف. بدونه، تحصل على خطأ.
س هل تدعم طريقة العرض المادية UPDATE/DELETE المباشر؟
ج لا. طريقة العرض المادية للقراءة فقط؛ يمكن تحديثها فقط عبر REFRESH. لتغييرها، حدث بيانات الجدول الأساسي ثم REFRESH مرة أخرى.
س ما الفرق بين WITH CASCADED CHECK OPTION و WITH LOCAL CHECK OPTION؟
ج CASCADED يفحص شرط طريقة العرض الحالية وجميع طرق العرض التابعة؛ LOCAL يفحص فقط شرط طريقة العرض الحالية. مع طرق العرض المتداخلة، CASCADED أكثر أماناً.
س هل يمكن بناء طريقة عرض مادية على طريقة عرض مادية أخرى؟
ج نعم. PostgreSQL تدعم طرق العرض المادية المتداخلة، لكن يجب تحديثها يدوياً بترتيب التبعية.


Web-Tutorial.com

فريق Web-Tutorial التقني

منصة دروس برمجية يديرها عدة مطورين. كل درس يتم كتابته ومراجعته بواسطة مطورين متخصصين في المجال. نعمل على ضمان دقة وموثوقية المحتوى — إذا لاحظت أي مشكلة، فيرجى إخبارنا.

100%