Crate-архитектура DataFusion: модульная структура
DataFusion — не монолит. Ядро разбито на отдельные Rust crate, каждый из которых решает одну задачу. Это позволяет зависеть только на нужные компоненты: если вам нужен только оптимизатор или только SQL-парсер — не тяните за собой весь execution engine.
Граф зависимостей
Зависимости направлены вниз: datafusion-sql зависит от datafusion-expr, но не от datafusion-physical-plan. Это позволяет использовать логический уровень без физического.
Что предоставляет каждый crate
datafusion-common
Фундаментальные типы, разделяемые всеми остальными crate:
// Ключевые типы из datafusion-common
pub struct DFSchema { ... } // Схема с qualifier (table.column)
pub enum ScalarValue { ... } // Скалярные значения (Int64, Utf8, Boolean, ...)
pub enum DataFusionError { ... } // Единый тип ошибок
pub struct Statistics { ... } // Статистика (кардинальность, min/max)
pub type Result<T> = std::result::Result<T, DataFusionError>;
DFSchema расширяет Arrow Schema именами таблиц (qualifiers): users.id вместо просто id. Это необходимо для разрешения неоднозначных ссылок в JOIN.
datafusion-expr
Логические выражения и планы:
// Типы из datafusion-expr
pub enum LogicalPlan { ... } // Дерево логических операций
pub enum Expr { ... } // Дерево выражений
pub trait TableProvider { ... } // Trait источника данных
pub trait ScalarUDF { ... } // User-defined scalar function
pub trait AggregateUDF { ... } // User-defined aggregate function
pub trait WindowUDF { ... } // User-defined window function
pub struct LogicalPlanBuilder { ... } // Builder для LogicalPlan
Это чисто декларативный уровень: LogicalPlan описывает, что вычислить, но не содержит кода выполнения. Если вы строите свой оптимизатор или транслятор планов — зависьте на datafusion-expr, не на весь datafusion.
datafusion-sql
SQL → LogicalPlan трансляция:
// SqlToRel: парсит AST (от sqlparser-rs) в LogicalPlan
pub struct SqlToRel<'a, S: ContextProvider> { ... }
pub trait ContextProvider {
fn get_table_source(&self, name: TableReference) -> Result<Arc<dyn TableProvider>>;
fn get_function_meta(&self, name: &str) -> Option<Arc<ScalarUDF>>;
fn get_aggregate_meta(&self, name: &str) -> Option<Arc<AggregateUDF>>;
// ...
}
ContextProvider — интерфейс для резолюции имён. SqlToRel использует его для разрешения таблиц и функций при построении LogicalPlan из AST.
datafusion-optimizer
Цепочка правил оптимизации:
pub struct Optimizer {
rules: Vec<Arc<dyn OptimizerRule>>,
}
pub trait OptimizerRule: Send + Sync {
fn name(&self) -> &str;
fn rewrite(
self,
plan: LogicalPlan,
config: &dyn OptimizerConfig,
) -> Result<Transformed<LogicalPlan>>;
}
Встроенные правила: FilterPushdown, ProjectionPushdown, ConstantFolding, CommonSubexprEliminate, EliminateLimit, SimplifyExpressions и десятки других. Вы можете добавлять свои правила или отключать встроенные.
datafusion-physical-plan
Физические операторы:
pub trait ExecutionPlan: Send + Sync { ... } // Trait физического оператора
pub struct FilterExec { ... }
pub struct ProjectionExec { ... }
pub struct HashJoinExec { ... }
pub struct SortMergeJoinExec { ... }
pub struct AggregateExec { ... }
pub struct SortExec { ... }
pub struct CoalescePartitionsExec { ... }
pub struct RepartitionExec { ... }
// ...
datafusion-physical-expr
Физические выражения — вычисления на Arrow данных:
pub trait PhysicalExpr: Send + Sync { ... }
pub trait AggregateExpr: Send + Sync { ... } // Аккумулятор агрегации
pub enum ColumnarValue { Array(ArrayRef), Scalar(ScalarValue) }
Отделён от datafusion-physical-plan чтобы физические выражения можно было использовать вне контекста полного плана (например, для вычисления одного выражения над RecordBatch).
datafusion-execution
Runtime-компоненты:
pub struct SessionConfig { ... } // Конфигурация сессии
pub struct TaskContext { ... } // Контекст выполнения партиции
pub struct RuntimeEnv { ... } // Ресурсы выполнения
pub trait MemoryPool: Send + Sync { ... } // Управление памятью
pub struct DiskManager { ... } // Spill-to-disk
datafusion-functions
Встроенные скалярные функции:
// Математические: abs, ceil, floor, round, power, sqrt, ...
// Строковые: upper, lower, trim, substring, concat, regexp_match, ...
// Дата/время: now, date_trunc, date_part, to_timestamp, ...
// Условные: coalesce, nullif, case, ...
// Крипто: md5, sha224, sha256, sha384, sha512
Отделены в свой crate, чтобы не включать все ~200 функций в минимальную сборку.
datafusion-catalog
Реализация системы каталогов:
pub trait CatalogProvider: Send + Sync { ... }
pub trait SchemaProvider: Send + Sync { ... }
pub struct MemoryCatalogProvider { ... } // In-memory каталог
pub struct MemorySchemaProvider { ... } // In-memory схема
Зависимость на конкретные crate
Полный DataFusion
[dependencies]
datafusion = "53.0" # Meta-crate: включает всё
Только логический уровень
[dependencies]
datafusion-common = "53.0"
datafusion-expr = "53.0"
datafusion-sql = "53.0"
datafusion-optimizer = "53.0"
# Нет datafusion-physical-plan — своя реализация выполнения
Этот паттерн используют системы, которые берут SQL-парсинг и оптимизацию от DataFusion, но выполняют план собственным движком (например, на GPU или в распределённом кластере).
Только выполнение
[dependencies]
datafusion-common = "53.0"
datafusion-physical-plan = "53.0"
datafusion-execution = "53.0"
# Нет datafusion-sql — план строится программно
Полезно, если вы получаете план от внешнего планировщика (Substrait, собственный DSL) и хотите только выполнить его.
Точки расширения по crate
| Crate | Точка расширения | Пример |
|---|---|---|
datafusion-expr | TableProvider | Кастомный источник данных |
datafusion-expr | ScalarUDF, AggregateUDF | Пользовательские функции |
datafusion-optimizer | OptimizerRule | Кастомное правило оптимизации |
datafusion-physical-plan | ExecutionPlan | Кастомный физический оператор |
datafusion-catalog | CatalogProvider, SchemaProvider | Внешний каталог |
datafusion-execution | MemoryPool | Кастомное управление памятью |
Каждая точка расширения — trait, который вы реализуете. DataFusion не требует fork: расширения подключаются через регистрацию в SessionContext.
Модуль 05 (Расширяемость) подробно разбирает каждую точку расширения с рабочими примерами. Здесь мы смотрим на архитектурный уровень — какой crate за что отвечает.
Версионирование
Все crate DataFusion выпускаются синхронно с одним номером версии. datafusion = "53.0" (релиз 2026-04-02) означает, что datafusion-common, datafusion-expr и все остальные — тоже 53.0.x. Это упрощает управление зависимостями: не нужно подбирать совместимые версии.
Релизы выходят ежемесячно. Breaking changes возможны между minor-версиями (DataFusion пока не обещает semver-совместимость на уровне API).
Итоги
- DataFusion разбит на 10+ crate с направленными зависимостями
-
datafusion-common— фундаментальные типы (DFSchema, ScalarValue, Error) -
datafusion-expr— логический уровень (LogicalPlan, Expr, TableProvider) -
datafusion-physical-plan— физические операторы (HashJoin, Sort, Aggregate) - Можно зависеть на подмножество: только SQL-парсинг, только оптимизацию, только выполнение
- Каждый crate предоставляет trait-ы для расширения — fork не нужен