يوفّر 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 data2. استبعاد الأعمدة
لا تُقرأ إلا الأعمدة المطلوبة:
# 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 selects3. التنفيذ الكسول
تُحوَّل عمليات متعددة إلى استعلام واحد:
# 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 | متقارب |
أبرز الاستنتاجات
- عمليات GroupBy: DataStore أسرع بما يصل إلى 19.93x
- مسارات المعالجة المعقدة: DataStore أسرع بمقدار 5-6x (ميزة SQL pushdown)
- عمليات التقطيع البسيطة: الأداء متقارب - والفارق ضئيل
- أفضل حالة استخدام: العمليات متعددة الخطوات مع GroupBy/التجميع
- 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 columns5. استفد من التجميعات في 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 everything7. العمليات المجمّعة
# 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 again8. استخدم 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 صف) | أيٌّ منهما (فرق يكاد لا يُذكر) |