يحتوي DataStore على وضعي توافق يحددان ما إذا كانت المخرجات تُهيَّأ لتتوافق مع pandas أو تُحسَّن لأداء Raw SQL.
نظرة عامة
| وضع | قيمة compat_mode |
الوصف |
|---|---|---|
| Pandas (افتراضي) | "pandas" |
توافق كامل مع سلوك pandas. يتم الحفاظ على ترتيب الصفوف، وMultiIndex، وset_index، وتصحيحات نوع البيانات، وآليات كسر التعادل في الفرز المستقر، وأغلفة -If/isNaN. |
| Performance | "performance" |
تنفيذ يعتمد على SQL أولًا. أُزيلت كل الأعباء الإضافية المرتبطة بتوافق pandas. أقصى إنتاجية، لكن قد تختلف النتائج بنيويًا عن pandas. |
ما الذي يعطّله وضع الأداء
| العبء الإضافي | سلوك وضع Pandas | سلوك وضع الأداء |
|---|---|---|
| الحفاظ على ترتيب الصفوف | حقن _row_id، وrowNumberInAllBlocks()، والاستعلامات الفرعية __orig_row_num__ |
معطّل — ترتيب الصفوف غير مضمون |
| فاصل كسر التعادل في الفرز المستقر | إضافة rowNumberInAllBlocks() ASC إلى ORDER BY |
معطّل — قد يكون ترتيب القيم المتعادلة عشوائيًا |
preserve_order في Parquet |
input_format_parquet_preserve_order=1 |
معطّل — يُسمح بقراءة Parquet على نحو متوازٍ |
ORDER BY التلقائي في GroupBy |
تتم إضافة ORDER BY group_key (الإعداد الافتراضي في pandas هو sort=True) |
معطّل — تُعاد المجموعات بترتيب عشوائي |
WHERE الخاصة بـ dropna في GroupBy |
تتم إضافة WHERE key IS NOT NULL (الإعداد الافتراضي في pandas هو dropna=True) |
معطّل — تُدرج مجموعات NULL |
set_index في GroupBy |
تُعيَّن مفاتيح التجميع كفهرس | معطّل — تبقى مفاتيح التجميع كأعمدة |
| أعمدة MultiIndex | تُرجع agg({'col': ['sum','mean']}) أعمدة MultiIndex |
معطّل — أسماء أعمدة مسطّحة (col_sum، col_mean) |
أغلفة -If/isNaN |
sumIf(col, NOT isNaN(col)) لتجاوز skipna |
معطّل — sum(col) مباشرةً (يتجاوز ClickHouse قيم NULL أصلًا) |
toInt64 مع count |
toInt64(count()) لمطابقة pandas int64 |
معطّل — يُرجع نوع بيانات SQL الأصلي |
fillna(0) لمجموع قيم كلّها NaN |
مجموع القيم كلّها NaN يُرجع 0 (سلوك pandas) | معطّل — يُرجع NULL |
| تصحيحات نوع البيانات | abs() من unsigned إلى signed، إلخ. |
معطّل — أنواع بيانات SQL الأصلية |
| الحفاظ على الفهرس | يستعيد الفهرس الأصلي بعد تنفيذ SQL | معطّل |
first()/last() |
argMin/argMax(col, rowNumberInAllBlocks()) |
any(col) / anyLast(col) — أسرع لكنه غير حتمي |
| التجميع في SQL واحد | تنفّذ ColumnExpr في groupby مع إنشاء DataFrame وسيط | يحقن LazyGroupByAgg في سلسلة العمليات lazy — استعلام SQL واحد |
تمكين وضع الأداء
استخدام كائن الإعداد
from chdb.datastore.config import config
# Enable performance mode
config.use_performance_mode()
# Back to pandas compatibility
config.use_pandas_compat()
# Check current mode
print(config.compat_mode) # 'pandas' or 'performance'استخدام دوال الوحدة
from chdb.datastore.config import set_compat_mode, CompatMode, is_performance_mode
# Enable performance mode
set_compat_mode(CompatMode.PERFORMANCE)
# Check
print(is_performance_mode()) # True
# Back to default
set_compat_mode(CompatMode.PANDAS)استخدام عبارات الاستيراد الجاهزة
from chdb import use_performance_mode, use_pandas_compat
use_performance_mode()
# ... high-performance operations ...
use_pandas_compat()متى تستخدم وضع الأداء
استخدم وضع الأداء عندما:
- تعالج مجموعات بيانات كبيرة (من مئات الآلاف إلى ملايين الصفوف)
- تشغّل أحمال عمل كثيفة التجميع (groupby, sum, mean, count)
- لا يهم ترتيب الصفوف (مثلًا: النتائج المجمّعة، والتقارير، ولوحات المعلومات)
- تريد أقصى إنتاجية SQL وأدنى عبء إضافي ممكن
- يكون استخدام الذاكرة مصدر قلق (قراءة Parquet المتوازية، ومن دون DataFrames وسيطة)
ابقَ في وضع pandas عندما:
- تحتاج إلى سلوك pandas الدقيق (ترتيب الصفوف، وMultiIndex، وأنواع البيانات)
- تعتمد على أن
first()/last()يعيدان بالفعل أول/آخر صف فعلي - تستخدم
shift(),diff(),cumsum()التي تعتمد على ترتيب الصفوف - تكتب اختبارات تقارن مخرجات DataStore مع pandas
اختلافات في السلوك
ترتيب الصفوف
في وضع الأداء، لا يُضمن ترتيب الصفوف في أي عملية. ويشمل ذلك:
- نتائج التصفية
- نتائج تجميع GroupBy
head()/tail()بدون استخدامsort_values()بشكل صريح- عمليات التجميع
first()/last()
إذا كنت بحاجة إلى نتائج مرتبة، فأضف sort_values() بشكل صريح:
config.use_performance_mode()
ds = pd.read_csv("data.csv")
# Unordered (fast)
result = ds.groupby("region")["revenue"].sum()
# Ordered (still fast, just adds ORDER BY)
result = ds.groupby("region")["revenue"].sum().sort_values()نتائج GroupBy
| الجانب | وضع Pandas | وضع الأداء |
|---|---|---|
| موضع مفتاح التجميع | الفهرس (عبر set_index) |
عمود عادي |
| ترتيب المجموعات | مرتّبة حسب المفتاح (افتراضيًا) | ترتيب عشوائي |
| مجموعات NULL | مستبعَدة (الإعداد الافتراضي dropna=True) |
مشمولة |
| تنسيق العمود | MultiIndex لتجميعات متعددة | أسماء مسطّحة (col_func) |
first()/last() |
حتمي (ترتيب الصفوف) | غير حتمي (any()/anyLast()) |
التجميع
config.use_performance_mode()
# Sum of all-NaN group returns NULL (not 0)
# Count returns native uint64 (not forced int64)
# No -If wrappers: sum() instead of sumIf()
result = ds.groupby("cat")["val"].sum()التنفيذ باستعلام SQL واحد
في وضع الأداء، يُنفَّذ تجميع ColumnExpr باستخدام groupby (مثل ds[condition].groupby('col')['val'].sum()) على شكل استعلام SQL واحد بدلًا من العملية ذات الخطوتين المستخدمة في وضع pandas:
config.use_performance_mode()
# Pandas mode: two SQL queries (filter → materialize → groupby)
# Performance mode: one SQL query (WHERE + GROUP BY in same query)
result = ds[ds["rating"] > 3.5].groupby("category")["revenue"].sum()
# Generated SQL (single query):
# SELECT category, sum(revenue) FROM data WHERE rating > 3.5 GROUP BY categoryوهذا يلغي التجسيد المادي الوسيط لـ DataFrame، ويمكن أن يقلّل بدرجة كبيرة من استخدام الذاكرة ووقت التنفيذ.
مقارنة مع محرك التنفيذ
وضع الأداء (compat_mode) ومحرك التنفيذ (execution_engine) هما بُعدان مستقلان في الإعداد:
| الإعداد | يتحكّم في | القيم |
|---|---|---|
execution_engine |
أي محرك ينفّذ العملية الحسابية | auto, chdb, pandas |
compat_mode |
ما إذا كانت ستُعاد صياغة المخرجات لتوافق pandas | pandas, performance |
يؤدي ضبط compat_mode='performance' إلى تعيين execution_engine='chdb' تلقائيًا، لأن وضع الأداء مُصمَّم لتنفيذ SQL.
from chdb.datastore.config import config
# These are independent
config.use_chdb() # Force chDB engine, keep pandas compat
config.use_performance_mode() # Force chDB + remove pandas overheadالاختبار باستخدام وضع الأداء
عند كتابة اختبارات لوضع الأداء، قد تختلف النتائج عن pandas من حيث ترتيب الصفوف وبنية التنسيق. استخدم الاستراتيجيات التالية:
الفرز ثم المقارنة (عمليات التجميع، عوامل التصفية)
# Sort both sides by the same columns before comparing
ds_result = ds.groupby("cat")["val"].sum()
pd_result = pd_df.groupby("cat")["val"].sum()
ds_sorted = ds_result.sort_index()
pd_sorted = pd_result.sort_index()
np.testing.assert_array_equal(ds_sorted.values, pd_sorted.values)التحقق من مدى القيم (الأولى/الأخيرة)
# first() with any() returns an arbitrary element from the group
result = ds.groupby("cat")["val"].first()
for group_key in groups:
assert result.loc[group_key] in group_values[group_key]البنية والعدد (LIMIT بدون ORDER BY)
# head() without sort_values: row set is non-deterministic
result = ds.head(5)
assert len(result) == 5
assert set(result.columns) == expected_columnsأفضل الممارسات
1. فعِّله مبكرًا في برنامجك النصي
from chdb.datastore.config import config
config.use_performance_mode()
# All subsequent operations benefit
ds = pd.read_parquet("data.parquet")
result = ds[ds["amount"] > 100].groupby("region")["amount"].sum()2. أضف فرزًا صريحًا عندما يكون ترتيب النتائج مهمًا
# For display or downstream processing that expects order
result = (ds
.groupby("region")["revenue"].sum()
.sort_values(ascending=False)
)3. استخدمه لأحمال العمل الدفعية/ETL
config.use_performance_mode()
# ETL pipeline — order doesn't matter, throughput does
summary = (ds
.filter(ds["date"] >= "2024-01-01")
.groupby(["region", "product"])
.agg({"revenue": "sum", "quantity": "sum", "rating": "mean"})
)
summary.to_df().to_parquet("summary.parquet")4. بدّل الأوضاع داخل الجلسة
# Performance mode for heavy computation
config.use_performance_mode()
aggregated = ds.groupby("cat")["val"].sum()
# Back to pandas mode for exact-match comparison
config.use_pandas_compat()
detailed = ds[ds["val"] > 100].head(10)- محرك التنفيذ — اختيار محرك التنفيذ (auto/chdb/pandas)
- دليل الأداء — نصائح عامة لتحسين الأداء
- أوجه الاختلاف الرئيسية عن pandas — فروق سلوكية