Skip to content
ClickHouse Docs
ClickHouse DocsClickHouse Docs

دليل الأداء

يوفّر DataStore تحسينات ملحوظة في الأداء مقارنةً بـ pandas في كثير من العمليات. يوضّح هذا الدليل سبب ذلك وكيفية تحسين أحمال العمل لديك.

لماذا DataStore أسرع

1. SQL Pushdown

تُنفَّذ العمليات مباشرةً في مصدر البيانات:

# pandas: Loads ALL data, then filters in memory
df = pd.read_csv("huge.csv")       # Load 10GB
df = df[df['year'] == 2024]        # Filter in Python

# DataStore: Filter at source
ds = pd.read_csv("huge.csv")       # Just metadata
ds = ds[ds['year'] == 2024]        # Filter in SQL
df = ds.to_df()                    # Only load filtered data

2. استبعاد الأعمدة

لا تُقرأ إلا الأعمدة المطلوبة:

# DataStore: Only reads name, age columns
ds = pd.read_parquet("wide_table.parquet")
result = ds.select('name', 'age').to_df()

# vs pandas: Reads all 100 columns, then selects

3. التنفيذ الكسول

تُحوَّل عمليات متعددة إلى استعلام واحد:

# DataStore: One optimized SQL query
result = (ds
    .filter(ds['amount'] > 100)
    .groupby('region')
    .agg({'amount': 'sum'})
    .sort('sum', ascending=False)
    .head(10)
    .to_df()
)

# Becomes:
# SELECT region, SUM(amount) FROM data
# WHERE amount > 100
# GROUP BY region ORDER BY sum DESC LIMIT 10

اختبار الأداء: DataStore مقابل pandas

بيئة الاختبار

  • البيانات: 10 ملايين صف
  • العتاد: حاسوب محمول عادي
  • صيغة الملف: CSV

النتائج

العملية pandas (مللي ثانية) DataStore (مللي ثانية) الفائز
عدد GroupBy 347 17 DataStore (19.93x)
عمليات مجمّعة 1,535 234 DataStore (6.56x)
pipeline معقّدة 2,047 380 DataStore (5.39x)
Filter متعدد+Sort+Head 1,963 366 DataStore (5.36x)
Filter+Sort+Head 1,537 350 DataStore (4.40x)
Head/Limit 166 45 DataStore (3.69x)
فائق التعقيد (أكثر من 10 عمليات) 1,070 338 DataStore (3.17x)
تجميع GroupBy 406 141 DataStore (2.88x)
Select+Filter+Sort 1,217 443 DataStore (2.75x)
Filter+GroupBy+Sort 466 184 DataStore (2.53x)
Filter+Select+Sort 1,285 533 DataStore (2.41x)
Sort (مفرد) 1,742 1,197 DataStore (1.45x)
Filter (مفرد) 276 526 متقارب
Sort (متعدد) 947 1,477 متقارب

أبرز الاستنتاجات

  1. عمليات GroupBy: DataStore أسرع بما يصل إلى 19.93x
  2. مسارات المعالجة المعقدة: DataStore أسرع بمقدار 5-6x (ميزة SQL pushdown)
  3. عمليات التقطيع البسيطة: الأداء متقارب - والفارق ضئيل
  4. أفضل حالة استخدام: العمليات متعددة الخطوات مع GroupBy/التجميع
  5. Zero-copy: لا يفرض to_df() أي عبء إضافي لتحويل البيانات

متى يكون DataStore هو الخيار الأفضل

التجميعات المكثفة

# DataStore excels: 19.93x faster
result = ds.groupby('category')['amount'].sum()

مسارات المعالجة المعقدة

# DataStore excels: 5-6x faster
result = (ds
    .filter(ds['date'] >= '2024-01-01')
    .filter(ds['amount'] > 100)
    .groupby('region')
    .agg({'amount': ['sum', 'mean', 'count']})
    .sort('sum', ascending=False)
    .head(20)
)

معالجة الملفات الكبيرة

# DataStore: Only loads what you need
ds = pd.read_parquet("huge_file.parquet")
result = ds.filter(ds['id'] == 12345).to_df()  # Fast!

عمليات على عدة أعمدة

# DataStore: Combines into single SQL
ds['total'] = ds['price'] * ds['quantity']
ds['is_large'] = ds['total'] > 1000
ds = ds.filter(ds['is_large'])

متى يكون pandas منافسًا

في معظم الحالات، يضاهي DataStore أداء pandas أو يتفوق عليه. ومع ذلك، قد يكون pandas أسرع قليلًا في الحالات التالية:

مجموعات بيانات صغيرة (<1,000 صف)

# For very small datasets, overhead is minimal for both
# Performance difference is negligible
small_df = pd.DataFrame({'x': range(100)})

عمليات التقطيع البسيطة

# Single slice operations without aggregation
df = df[df['x'] > 10]  # pandas slightly faster
ds = ds[ds['x'] > 10]  # DataStore comparable

دوال لامبدا مخصّصة بلغة بايثون

# pandas required for custom Python code
def complex_function(row):
    return custom_logic(row)

df['result'] = df.apply(complex_function, axis=1)

تكامل DataFrame بتقنية zero-copy

يستخدم DataStore تقنية zero-copy لقراءة pandas DataFrames وكتابتها. وهذا يعني:

# to_df() does NOT copy data - it's a zero-copy operation
result = ds.filter(ds['x'] > 10).to_df()  # No data conversion overhead

# Same for creating DataStore from DataFrame
ds = DataStore(existing_df)  # No data copy

النتائج الرئيسية:

  • to_df() عمليًا بلا تكلفة - من دون تسلسل أو نسخ للذاكرة
  • إنشاء DataStore من pandas DataFrame يتم فورًا
  • الذاكرة مشتركة بين DataStore وpandas views

نصائح لتحسين الأداء

1. فعِّل وضع الأداء لأحمال العمل المكثفة

بالنسبة إلى أحمال العمل التي تكثر فيها عمليات التجميع ولا تحتاج فيها إلى تنسيق مخرجات pandas الدقيق (ترتيب الصفوف، أعمدة MultiIndex، وتصحيحات نوع البيانات)، فعِّل وضع الأداء لتحقيق أقصى إنتاجية:

from chdb.datastore.config import config

config.use_performance_mode()

# Now all operations use SQL-first execution with no pandas overhead:
# - Parallel Parquet reading (no preserve_order)
# - Single-SQL aggregation (filter+groupby in one query)
# - No row-order preservation overhead
# - No MultiIndex, no dtype corrections
result = (ds
    .filter(ds['amount'] > 100)
    .groupby('region')
    .agg({'amount': ['sum', 'mean', 'count']})
)

التحسّن المتوقع: سرعة أعلى بما يصل إلى 2-8 مرات في أعباء عمل filter+groupby، مع تقليل استخدام الذاكرة عند التعامل مع ملفات Parquet الكبيرة.

راجع وضع الأداء للاطلاع على التفاصيل الكاملة.

2. استخدم Parquet بدلًا من CSV

# CSV: Slower, reads entire file
ds = pd.read_csv("data.csv")

# Parquet: Faster, columnar, compressed
ds = pd.read_parquet("data.parquet")

# Convert once, benefit forever
df = pd.read_csv("data.csv")
df.to_parquet("data.parquet")

التحسّن المتوقع: قراءة أسرع بمقدار 3-10x

3. نفّذ التصفية مبكرًا

# Good: Filter first, then aggregate
result = (ds
    .filter(ds['date'] >= '2024-01-01')  # Reduce data early
    .groupby('category')['amount'].sum()
)

# Less optimal: Process all data
result = (ds
    .groupby('category')['amount'].sum()
    .filter(ds['sum'] > 1000)  # Filter too late
)

4. حدّد الأعمدة المطلوبة فقط

# Good: Column pruning
result = ds.select('name', 'amount').filter(ds['amount'] > 100)

# Less optimal: All columns loaded
result = ds.filter(ds['amount'] > 100)  # Loads all columns

5. استفد من التجميعات في SQL

# GroupBy is where DataStore shines
# Up to 20x speedup!
result = ds.groupby('category').agg({
    'amount': ['sum', 'mean', 'count', 'max'],
    'quantity': 'sum'
})

6. استخدم الدالة head() بدلًا من الاستعلامات الكاملة

# Don't load entire result if you only need a sample
result = ds.filter(ds['type'] == 'A').head(100)  # LIMIT 100

# Avoid this for large results
# result = ds.filter(ds['type'] == 'A').to_df()  # Loads everything

7. العمليات المجمّعة

# Good: Single execution
result = ds.filter(ds['x'] > 10).filter(ds['y'] < 100).to_df()

# Bad: Multiple executions
result1 = ds.filter(ds['x'] > 10).to_df()  # Execute
result2 = result1[result1['y'] < 100]       # Execute again

8. استخدم explain() لتحسين الأداء

# View the query plan before executing
query = ds.filter(...).groupby(...).agg(...)
query.explain()  # Check if operations are pushed down

# Then execute
result = query.to_df()

تحليل أداء عبء العمل لديك

فعّل تحليل الأداء

from chdb.datastore.config import config, get_profiler

config.enable_profiling()

# Run your workload
result = your_pipeline()

# View report
profiler = get_profiler()
profiler.report()

تحديد نقاط الاختناق

Performance Report
==================
Step                    Duration    % Total
----                    --------    -------
SQL execution           2.5s        62.5%     <- Bottleneck!
read_csv                1.2s        30.0%
Other                   0.3s        7.5%

مقارنة النُّهج

# Test approach 1
profiler.reset()
result1 = approach1()
time1 = profiler.get_steps()[-1]['duration_ms']

# Test approach 2
profiler.reset()
result2 = approach2()
time2 = profiler.get_steps()[-1]['duration_ms']

print(f"Approach 1: {time1:.0f}ms")
print(f"Approach 2: {time2:.0f}ms")

ملخص أفضل الممارسات

الممارسة الأثر
فعّل وضع الأداء أسرع بمقدار 2-8 مرات لأعباء عمل التجميع
استخدم ملفات Parquet أسرع بمقدار 3-10 مرات في القراءة
صفِّ البيانات مبكرًا تقليل معالجة البيانات
حدّد الأعمدة المطلوبة تقليل عمليات الإدخال/الإخراج واستهلاك الذاكرة
استخدم GroupBy/التجميعات أسرع بما يصل إلى 20 مرة
استخدم العمليات المجمّعة تجنّب التنفيذ المتكرر
حلّل الأداء قبل التحسين اعثر على مواضع الاختناق الفعلية
استخدم explain() تحقّق من تحسين الاستعلام
استخدم head() للعينات تجنّب المسح الكامل للجدول

دليل اتخاذ القرار السريع

عبء العمل لديك التوصية
GroupBy/التجميع استخدم DataStore
مسار معالجة معقد متعدد الخطوات استخدم DataStore
ملفات كبيرة مع عوامل تصفية استخدم DataStore
عمليات التقطيع البسيطة أيٌّ منهما (أداء متقارب)
دوال لامبدا مخصّصة في بايثون استخدم pandas أو أجّل التحويل
بيانات صغيرة جدًا (<1,000 صف) أيٌّ منهما (فرق يكاد لا يُذكر)
Navigation