Skip to content
ClickHouse Docs
ClickHouse DocsClickHouse Docs

الدالة explain()

تعرض الدالة explain() خطة تنفيذ لاستعلام DataStore، مما يساعدك على فهم العمليات التي ستُنفَّذ وعبارات SQL التي سيتم توليدها.

الاستخدام الأساسي

from pathlib import Path
Path("sales.csv").write_text("""\
region,product,category,amount,quantity,price,date,order_id
East,Widget,Electronics,5200,10,120,2024-01-15,1001
West,Gadget,Electronics,800,5,160,2024-02-20,1002
East,Gizmo,Home,6500,3,100,2024-03-10,1003
North,Widget,Electronics,4500,6,150,2024-06-18,1004
West,Gadget,Electronics,2000,8,250,2024-09-14,1005
""")

from chdb import datastore as pd

ds = pd.read_csv("sales.csv")

query = (ds
    .filter(ds['amount'] > 1000)
    .groupby('region')
    .agg({'amount': ['sum', 'mean']})
    .sort('sum', ascending=False)
)

# View execution plan
query.explain()

الصيغة

explain(verbose=False) -> None

المعلمات:

المعلمة النوع الافتراضي الوصف
verbose bool False عرض بيانات وصفية إضافية

صيغة الإخراج

الإخراج القياسي

================================================================================
Execution Plan (in execution order)
================================================================================

 [1] 📊 Data Source: file('sales.csv', 'csv')

Operations:
────────────────────────────────────────────────────────────────────────────────
    ️  Segment 1 [chDB] (from source): Operations 2-5
    ️  Note: SQL operations after Pandas ops use Python() table function

 [2] 🚀 [chDB] WHERE: "amount" > 1000
 [3] 🚀 [chDB] GROUP BY: region
 [4] 🚀 [chDB] AGGREGATE: sum(amount), avg(amount)
 [5] 🚀 [chDB] ORDER BY: sum DESC

────────────────────────────────────────────────────────────────────────────────
Final State: 📊 Pending (lazy, not yet executed)
             └─> Will execute when print(), .to_df(), .execute() is called

────────────────────────────────────────────────────────────────────────────────
Generated SQL Query:
────────────────────────────────────────────────────────────────────────────────

SELECT region, SUM(amount) AS sum, AVG(amount) AS mean
FROM file('sales.csv', 'csv')
WHERE "amount" > 1000
GROUP BY region
ORDER BY sum DESC

================================================================================

دليل الأيقونات

الأيقونة المعنى
📊 مصدر بيانات
🚀 عملية chDB ‏(SQL)
🐼 عملية pandas

الإخراج التفصيلي

query.explain(verbose=True)

يعرض الوضع التفصيلي تفاصيل إضافية لكل عملية، بما في ذلك استعلام SQL الكامل مع آليات داخلية لتتبّع ترتيب الصفوف.


مراحل التنفيذ الثلاث

تعرض مخرجات EXPLAIN العمليات عبر ثلاث مراحل:

المرحلة 1: بناء استعلام SQL (التنفيذ المؤجل)

العمليات التي تُترجم إلى SQL:

  1. Source: file('sales.csv', 'CSVWithNames')
  2. Filter: amount > 1000      
  3. GroupBy: region
  4. Aggregate: sum(amount)

المرحلة 2: نقطة التنفيذ

عند تفعيل المُشغِّل:

  5. Execute SQL -> DataFrame
     Trigger: to_df() called

المرحلة 3: العمليات على DataFrame

العمليات بعد التنفيذ:

  6. [pandas] pivot_table(...)
  7. [pandas] apply(custom_func)

فهم خطة التنفيذ

معلومات المصدر

Source: file('sales.csv', 'CSVWithNames')
  • file() - دالة الجدول file() في ClickHouse
  • 'CSVWithNames' - تنسيق ملف يتضمن صف عناوين

أنواع المصادر الأخرى:

Source: s3('bucket/data.parquet', ...)
Source: mysql('host', 'db', 'table', ...)
Source: __dataframe__  (pandas DataFrame input)

عمليات التصفية

Filter: amount > 1000 AND status = 'active'

يوضح بند WHERE الذي سيُطبَّق.

GroupBy والتجميع

GroupBy: region, category
Aggregate: sum(amount), avg(amount), count(id)

يعرض الأعمدة المستخدمة في GROUP BY ودوال التجميع.

عمليات الترتيب

Sort: sum DESC, region ASC

يعرض عبارة ORDER BY.

عمليات LIMIT

Limit: 10
Offset: 100

يعرض LIMIT وOFFSET.


معلومات المحرّك

عند استخدام الوضع المفصّل، يمكنك رؤية المحرّك الذي سيُستخدم:

Filter: amount > 1000
  - Engine: chdb
  - Pushdown: Yes

Apply: custom_function
  - Engine: pandas
  - Pushdown: No

Pushdown

  • نعم: ستُنفَّذ العملية في مصدر البيانات (SQL)
  • لا: تتطلب العملية تنفيذها باستخدام pandas

أمثلة

استعلام بسيط

from pathlib import Path
Path("data.csv").write_text("""\
name,age,city,salary,department
Alice,25,NYC,55000,Engineering
Bob,30,LA,65000,Product
Charlie,35,NYC,80000,Engineering
Diana,28,SF,70000,Design
Eve,42,NYC,95000,Product
""")

ds = pd.read_csv("data.csv")
ds.filter(ds['age'] > 25).explain()
================================================================================
Execution Plan (in execution order)
================================================================================

 [1] 📊 Data Source: file('data.csv', 'csv')

Operations:
────────────────────────────────────────────────────────────────────────────────
    ️  Segment 1 [chDB] (from source): Operations 2-2

 [2] 🚀 [chDB] WHERE: "age" > 25

────────────────────────────────────────────────────────────────────────────────
Generated SQL Query:
────────────────────────────────────────────────────────────────────────────────

SELECT * FROM file('data.csv', 'csv') WHERE "age" > 25

================================================================================

التجميع المعقّد

query = (ds
    .filter(ds['date'] >= '2024-01-01')
    .filter(ds['amount'] > 100)
    .select('region', 'category', 'amount')
    .groupby('region', 'category')
    .agg({
        'amount': ['sum', 'mean', 'count']
    })
    .sort('sum', ascending=False)
    .limit(20)
)
query.explain()
================================================================================
Execution Plan (in execution order)
================================================================================

 [1] 📊 Data Source: file('sales.csv', 'csv')

Operations:
────────────────────────────────────────────────────────────────────────────────
    ️  Segment 1 [chDB] (from source): Operations 2-8

 [2] 🚀 [chDB] WHERE: "date" >= '2024-01-01'
 [3] 🚀 [chDB] WHERE: "amount" > 100
 [4] 🚀 [chDB] SELECT: region, category, amount
 [5] 🚀 [chDB] GROUP BY: region, category
 [6] 🚀 [chDB] AGGREGATE: sum(amount), avg(amount), count(amount)
 [7] 🚀 [chDB] ORDER BY: sum DESC
 [8] 🚀 [chDB] LIMIT: 20

────────────────────────────────────────────────────────────────────────────────
Generated SQL Query:
────────────────────────────────────────────────────────────────────────────────

SELECT region, category, 
       SUM(amount) AS sum, 
       AVG(amount) AS mean, 
       COUNT(amount) AS count
FROM file('sales.csv', 'csv')
WHERE "date" >= '2024-01-01' AND "amount" > 100
GROUP BY region, category
ORDER BY sum DESC
LIMIT 20

================================================================================

SQL وpandas معًا

عندما يتعذر تنفيذ جميع العمليات بالكامل داخل SQL، تُظهر الخطة عدة مقاطع:

query = (ds
    .filter(ds['age'] > 25)           # SQL
    .groupby('city')                   # SQL
    .agg({'salary': 'mean'})           # SQL
    .apply(lambda x: x * 1.1)          # pandas (triggers segment split)
    .filter(ds['mean'] > 50000)        # SQL (new segment)
)
query.explain()
================================================================================
Execution Plan (in execution order)
================================================================================

 [1] 📊 Data Source: file('data.csv', 'csv')

Operations:
────────────────────────────────────────────────────────────────────────────────
    ️  Segment 1 [chDB] (from source): Operations 2-4
    ️  Segment 2 [Pandas] (on DataFrame): Operation 5
    ️  Segment 3 [chDB] (on DataFrame): Operation 6
    ️  Note: SQL operations after Pandas ops use Python() table function

 [2] 🚀 [chDB] WHERE: "age" > 25
 [3] 🚀 [chDB] GROUP BY: city
 [4] 🚀 [chDB] AGGREGATE: avg(salary)
 [5] 🐼 [Pandas] APPLY: lambda
 [6] 🚀 [chDB] WHERE: "mean" > 50000

================================================================================

استكشاف الأخطاء وإصلاحها باستخدام explain()

تحقّق من منطق التصفية

# Verify your filter is correct
query = ds.filter((ds['age'] > 25) & (ds['city'] == 'NYC'))
query.explain()
# Output shows: Filter: age > 25 AND city = 'NYC'

تحقّق من تحديد العمود

# Check column pruning
query = ds.select('name', 'age').filter(ds['age'] > 25)
query.explain()
# Output shows: SELECT name, age FROM ... WHERE age > 25

فهم التجميع

# Check aggregation functions
query = ds.groupby('dept').agg({'salary': ['sum', 'mean', 'std']})
query.explain()
# Output shows: SELECT dept, SUM(salary), AVG(salary), stddevPop(salary)

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

1. تحقّق قبل تنفيذ الاستعلامات الكبيرة

# Always explain first for large data
query = ds.complex_pipeline()
query.explain()  # Check plan

# If plan looks correct
result = query.to_df()  # Execute

2. استخدم تفصيلي لاستكشاف الأخطاء وإصلاحها

# When something seems wrong
query.explain(verbose=True)
# Shows engine selection and pushdown info

3. قارن مع to_sql()

# explain() shows the plan
query.explain()

# to_sql() shows just the SQL
print(query.to_sql())

# Both useful for different purposes

4. التحقّق من حالة Pushdown

# Verbose mode shows if operations are pushed down
query.explain(verbose=True)

# If Pushdown: No, operation runs in pandas
# Consider restructuring query for better performance
Navigation