Pandas & NumPy Academy · درس

Parquet: تخزين عمودي سريع

اكتب Pandas DataFrame إلى Parquet باستخدام to_parquet()، واقرأه بسرعة أكبر من CSV، واستخدم تقليص الأعمدة لتحميل الحقول المطلوبة فقط.

الدرس 4 من 413 خطوة

Parquet: تخزين عمودي سريع درس مجاني في Pandas & NumPy Academy على CoddyKit. هذا هو الدرس 4 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Pandas & NumPy Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Pandas & NumPy Academy 4 دروس في المجموع.

ما هو Parquet؟

إن Apache Parquet هو تنسيق ملفات ثنائي عمودي مصمم لأحمال العمل التحليلية. فعلى خلاف CSV، الذي يخزن البيانات صفًا تلو الآخر كنص، يخزن Parquet كل عمود في كتلة متجاورة، ويضغطه بكفاءة، ويرمّز البيانات الوصفية. وهذا يجعله أسرع بكثير في الاستعلامات التي تقرأ بضعة أعمدة فقط من جدول عريض. ويُعد Parquet التنسيق القياسي الفعلي في بحيرات البيانات (AWS S3 وGoogle Cloud Storage)، كما تدعمه Pandas وDask وSpark وBigQuery دعمًا أصليًا.

كتابة Parquet باستخدام to_parquet()

يتم تحويل Pandas DataFrame إلى Parquet باستدعاء طريقة واحدة: df.to_parquet('output.parquet'). والمحرك الافتراضي هو pyarrow (يُثبَّت باستخدام pip install pyarrow). يحافظ Parquet على أنواع بيانات الأعمدة بدقة؛ فلا تعود أعمدة التاريخ تُقرأ كسلاسل نصية. كما يدعم الضغط مباشرةً باستخدام المعامل compression؛ إذ يوفر 'snappy' قراءة وكتابة سريعتين مع ضغط متوسط، بينما يوفر 'gzip' ضغطًا أعلى مقابل انخفاض السرعة.

import pandas as pd
import numpy as np

# Create a sample DataFrame
np.random.seed(0)
df = pd.DataFrame({
    'date': pd.date_range('2024-01-01', periods=100000, freq='T'),
    'value': np.random.randn(100000),
    'category': np.random.choice(['A', 'B', 'C'], 100000)
})

# Write to Parquet
df.to_parquet('data.parquet', index=False, compression='snappy')
print('Written to data.parquet')

قراءة Parquet باستخدام read_parquet()

يقرأ pd.read_parquet('output.parquet') الملف ويعيده إلى DataFrame. وبالمقارنة مع قراءة ملف CSV المكافئ، تكون قراءة Parquet عادةً أسرع من 5 إلى 10 مرات في الجداول العريضة التي تحتوي على أعمدة كثيرة. وتُحفظ أنواع البيانات بدقة؛ فتبقى التواريخ من النوع datetime64، وتبقى الفئات من النوع category، وتبقى الأعداد الصحيحة من النوع int32 أو int64 كما خُزنت. ولا حاجة إلى استنتاج نوع البيانات، لأن البيانات الوصفية مضمنة في الملف.

import pandas as pd
import time

# Read Parquet
start = time.time()
df = pd.read_parquet('data.parquet')
print(f'Read Parquet: {time.time()-start:.3f}s')
print(df.dtypes)
print(df.shape)

تقليص الأعمدة: قراءة الأعمدة المطلوبة فقط

تتمثل أكبر ميزة للتخزين العمودي في تقليص الأعمدة؛ إذ يمكنك قراءة أعمدة محددة فقط دون فحص بقية الملف. مرّر قائمة بأسماء الأعمدة إلى المعامل columns. فإذا كان جدول مكوّن من 100 عمود يحتوي على 100 ميغابايت لكل عمود، وكنت تحتاج إلى 3 أعمدة فقط، فسيقرأ Parquet مقدار 3 ميغابايت بدلًا من 10 غيغابايت. أما CSV فيجب أن يفحص كل محرف لاستخراج أي عمود. وهذا يجعل Parquet مثاليًا للجداول العريضة في مسارات التحليل.

import pandas as pd

# Only load the 2 columns needed for this analysis
df = pd.read_parquet('large_table.parquet',
                     columns=['date', 'revenue'])
print(df.columns.tolist())
print(df.shape)
print(df.memory_usage(deep=True).sum() / 1e6, 'MB loaded')

تصفية مجموعات الصفوف (دفع المسندات)

يخزن Parquet إحصاءات (الحد الأدنى/الأقصى) لكل مجموعة صفوف (أي كتلة من الصفوف) في تذييل الملف. وعند تطبيق مرشح باستخدام المعامل filters، يتجاوز القارئ مجموعات الصفوف الكاملة التي لا يمكن أن يطابقها المرشح — ويُسمى ذلك دفع المسندات. فعلى سبيل المثال، تؤدي تصفية التواريخ في ملف Parquet مرتب زمنيًا إلى تجاوز كتل الأشهر الكاملة الواقعة خارج النطاق، مع قراءة الأجزاء ذات الصلة فقط. ويدعم محرك pyarrow هذه الميزة دعمًا أصليًا.

import pandas as pd

# Filter using predicate pushdown — row groups outside range are skipped
df = pd.read_parquet(
    'time_series.parquet',
    columns=['date', 'value'],
    filters=[('date', '>=', '2024-06-01'),
              ('date', '<', '2024-07-01')]
)
print(f'Loaded {len(df):,} rows (June only)')
print(df.head())

Parquet مقابل CSV: مقارنة

إليك مقارنة عملية بين Parquet وCSV لمجموعة بيانات تتكون من 10 ملايين صف و20 عمودًا:

  • حجم الملف: CSV نحو 2 غيغابايت، وParquet (snappy) نحو 400 ميغابايت
  • وقت القراءة (جميع الأعمدة): CSV نحو 15 ثانية، وParquet نحو ثانيتين
  • وقت القراءة (3 أعمدة): CSV نحو 15 ثانية (إذ يجب فحص جميع الأعمدة)، وParquet نحو 0.3 ثانية
  • الحفاظ على أنواع البيانات: يفقد CSV أنواع البيانات، بينما يحافظ Parquet عليها
  • قابلية القراءة البشرية: CSV نعم، وParquet لا (ثنائي)

في مسارات المعالجة الإنتاجية التي تُكتب فيها البيانات مرة واحدة وتُقرأ مرات عديدة، يكون Parquet تقريبًا الخيار الأفضل دائمًا.

مجموعات بيانات Parquet المقسمة

بالنسبة إلى مجموعات البيانات الكبيرة جدًا، يدعم Parquet مجموعات البيانات المقسمة؛ إذ تُقسَّم البيانات إلى عدة ملفات منظمة في تسلسل هرمي للمجلدات وفق قيم الأعمدة. فعلى سبيل المثال، يؤدي التقسيم حسب السنة والشهر إلى إنشاء data/year=2024/month=01/part.parquet. وعند قراءة مجموعة بيانات مقسمة، تُصفّى المجلدات المطابقة للاستعلام تلقائيًا. وهذا هو التخطيط القياسي في بحيرات البيانات، كما يتيح إجراء استعلامات النطاق بكفاءة على مليارات الصفوف.

import pandas as pd

# Write a partitioned dataset (requires pyarrow)
df = pd.read_parquet('all_data.parquet')
df['year'] = df['date'].dt.year
df['month'] = df['date'].dt.month

df.to_parquet(
    'partitioned_data/',
    partition_cols=['year', 'month'],
    index=False
)
# Creates: partitioned_data/year=2024/month=1/part-0.parquet etc.

قراءة مجموعات البيانات المقسمة

تتم قراءة دليل Parquet المقسم بالطريقة نفسها التي يُقرأ بها ملف واحد؛ إذ يكتشف Pandas (عبر pyarrow) جميع ملفات التقسيم تلقائيًا. وتُضمَّن قيم عمود التقسيم كأعمدة في DataFrame الناتج. يمكنك أيضًا استخدام filters للاستفادة من تقليص التقسيمات، حيث يتم تجاوز أشجار المجلدات الفرعية الكاملة بناءً على قيم عمود التقسيم. وهذا يجعل الاستعلام في مجموعة بيانات مقسمة حجمها 1 تيرابايت يبدو كأنه قراءة بضعة ميغابايتات.

import pandas as pd

# Read the entire partitioned dataset
df_all = pd.read_parquet('partitioned_data/')
print('All years:', df_all['year'].unique())

# Read only 2024 data using partition pruning
df_2024 = pd.read_parquet(
    'partitioned_data/',
    filters=[('year', '==', 2024)]
)
print('2024 rows:', len(df_2024))

Parquet مع Dask

يقرأ Dask ملفات Parquet ويكتبها دعمًا أصليًا باستخدام dd.read_parquet() وddf.to_parquet(). ويصبح كل ملف في دليل Parquet المقسم تقسيمًا واحدًا في Dask، مما يتيح إجراء عمليات القراءة بالتوازي الكامل. كما يستفيد Dask من دفع المسندات عند تحديد المرشحات. وتُعد كتابة نتيجة Dask كبيرة إلى مجموعة بيانات Parquet مقسمة الطريقة القياسية لإنتاج المخرجات في مسارات هندسة البيانات الحديثة.

import dask.dataframe as dd

# Read partitioned Parquet with Dask (each file = one partition)
ddf = dd.read_parquet('partitioned_data/',
                      columns=['date', 'revenue', 'region'],
                      filters=[('year', '==', 2024)])

# Compute aggregation in parallel
result = ddf.groupby('region')['revenue'].sum().compute()
print(result.sort_values(ascending=False))

خيارات الضغط والترميز

يدعم Parquet خوارزميات ضغط متعددة ومخططات ترميز داخلية. يعطي Snappy (الافتراضي) الأولوية للسرعة مع ضغط متوسط. ويحقق Gzip ملفات أصغر بنحو 30%، لكنه أبطأ في القراءة والكتابة. أما Zstd فيوازن بين السرعة والضغط بصورة أفضل من كليهما. وبالنسبة إلى أعمدة الأعداد الصحيحة، يطبّق Parquet تلقائيًا ترميز الفروقات أو الترميز بالقاموس لتقليل الحجم أكثر، من دون الحاجة إلى أي إعداد إضافي من جانبكم.

import pandas as pd
import numpy as np

np.random.seed(0)
df = pd.DataFrame({'id': range(500000), 'val': np.random.randn(500000)})

for comp in ['snappy', 'gzip', 'zstd']:
    fname = f'data_{comp}.parquet'
    df.to_parquet(fname, compression=comp, index=False)
    import os
    size_mb = os.path.getsize(fname) / 1e6
    print(f'{comp}: {size_mb:.2f} MB')

استبدال CSV في مسار العمل

إن أبسط طريقة لاعتماد Parquet هي إضافة خطوة تحويل تُنفّذ مرة واحدة في بداية المشروع: اقرأ ملف CSV مرة واحدة، ونظّف أنواع البيانات وحوّلها، ثم احفظه بصيغة Parquet. بعد ذلك، تقرأ جميع عمليات التشغيل اللاحقة ملف Parquet بدلًا من CSV. ويمنحكم هذا فوائد فورية في السرعة ومساحة التخزين مع الحد الأدنى من التغييرات البرمجية. وبالنسبة إلى البيانات الجديدة التي تصل بصيغة CSV (مثل عمليات التصدير الليلية)، أضيفوا إلى مسار العمل خطوة تحويل تكتب البيانات بصيغة Parquet قبل بدء أي تحليل.

import pandas as pd

# One-time conversion
df = pd.read_csv('raw_data.csv',
                 parse_dates=['date'],
                 dtype={'category': 'category',
                        'amount': 'float32'})
df.to_parquet('clean_data.parquet', index=False)

# All future reads use Parquet
df_fast = pd.read_parquet('clean_data.parquet')
print('Loaded from Parquet:', df_fast.dtypes.to_dict())

تحقق سريع

اختبروا مدى فهمكم لمفاهيم تحليل البيانات التي تناولها هذا الدرس.

مراجعة الدرس

تعلّمتم في هذا الدرس أن to_parquet() و read_parquet() يوفّران إدخالًا وإخراجًا للملفات أسرع وأصغر حجمًا مع الحفاظ على أنواع البيانات، مقارنةً بـ CSV؛ وأن اقتطاع الأعمدة باستخدام المعامل columns يقرأ الأعمدة المطلوبة فقط، متجنبًا فحص الملف بالكامل؛ وأن مجموعات بيانات Parquet المُقسّمة والمنظّمة حسب قيم الأعمدة تتيح اقتطاع الأقسام لإجراء استعلامات نطاقية بكفاءة على بحيرات البيانات الكبيرة. بعد ذلك، سنصل Pandas بقواعد البيانات العلائقية باستخدام SQLAlchemy.

البدء مجانًا

تعلم Python مع معلم ذكاء اصطناعي — مجانًا

اكتب وقم بتشغيل أكوادك الفعلية في المتصفح، واحصل على مساعدة فورية من معلم ذكاء اصطناعي متاح 24/7، واستمر من حيث توقفت على الويب أو في التطبيق.

الدورات
30
الدروس
120

الأسئلة الشائعة

هل درس «Parquet: تخزين عمودي سريع» مجاني؟

نعم — نص درس «Parquet: تخزين عمودي سريع» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Pandas & NumPy Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Pandas & NumPy Academy 4 دروس في المجموع.

ماذا ستتعلم في «Parquet: تخزين عمودي سريع»؟

اكتب Pandas DataFrame إلى Parquet باستخدام to_parquet()، واقرأه بسرعة أكبر من CSV، واستخدم تقليص الأعمدة لتحميل الحقول المطلوبة فقط. تتمرن على Pandas & NumPy Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ Pandas & NumPy Academy؟

لا تُشترط خبرة سابقة. Pandas & NumPy Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 4 من أصل 4.

كم من الوقت يستغرق درس «Parquet: تخزين عمودي سريع»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس Pandas & NumPy Academy هذا؟

نعم. كل درس في Pandas & NumPy Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. بث CSV باستخدام chunksize
  2. التجميع التدريجي عبر الدفعات
  3. مقدمة إلى Dask DataFrames
  4. Parquet: تخزين عمودي سريع
← العودة إلى Pandas & NumPy Academy