Files
doris/regression-test/data/pythonudf_p0/test_pythonudf_schema_check.out
T
yangshijieandyangshijie 4a37aec7d2 [Feat](udf) Support Python UDF/UDAF/UDTF for Doris (#59543)
This PR references ByteDance's implementation. Co-Author: @WencongLiu

## Description

This PR introduces native support for **Python User-Defined Functions
(UDF), User-Defined Aggregate Functions (UDAF), and User-Defined Table
Functions (UDTF)** in Doris, enabling users to extend SQL capabilities
with custom Python logic for complex data processing scenarios.

## Key Features

### 🚀 **Three Function Types**
- **UDF**: Scalar functions with row-by-row or vectorized execution
(3-10x performance gain with Pandas/Arrow mode)
- **UDAF**: Snowflake-style stateful aggregation with distributed merge
support
- **UDTF**: Table-valued functions that generate multiple output rows
from a single input row

### 🔧 **Production-Grade Architecture**
- **High-Performance Communication**: Arrow Flight RPC over Unix sockets
with zero-copy columnar data transfer
- **Multi-Version Support**: Flexible environment management via Conda
or venv, allowing different UDFs to use different Python versions (e.g.,
3.9, 3.10, 3.12)

### 🎯 **Deep Integration**
- Seamless integration with Doris vectorized execution engine
- Native support for Doris data types (including complex types like
ARRAY, MAP, STRUCT)
- Automatic conversion between Doris types and Python/Arrow types

## Architecture Highlights

```
┌──────────────────────────────────────────────────────┐
│  Doris BE (C++)                                      │
│  ┌────────────────────────────────────────────────┐  │
│  │  PythonServerManager (Process Pool)            │  │
│  │  ├─ Health Check Thread (60s interval)         │  │
│  │  ├─ Load Balancing (min ref count)             │  │
│  │  └─ Auto Recovery (dead process detection)     │  │
│  └────────────────────────────────────────────────┘  │
│  ┌────────────────────────────────────────────────┐  │
│  │  PythonClient (Arrow Flight RPC)               │  │
│  │  ├─ UDF: Scalar/Vectorized evaluation          │  │
│  │  ├─ UDAF: Stateful aggregation with merge      │  │
│  │  └─ UDTF: ListArray batch processing           │  │
│  └────────────────────────────────────────────────┘  │
└──────────────────────────────────────────────────────┘
                      ↕ Unix Socket
┌──────────────────────────────────────────────────────┐
│  Python Process (python_server.py)                   │
│  ┌────────────────────────────────────────────────┐  │
│  │  FlightServer (Arrow Flight bidirectional)     │  │
│  │  ├─ AdaptivePythonUDF (auto mode selection)    │  │
│  │  ├─ UDAFStateManager (Snowflake interface)     │  │
│  │  └─ UDFLoader (inline/module code execution)   │  │
│  └────────────────────────────────────────────────┘  │
└──────────────────────────────────────────────────────┘
```

## Configuration

Add to `be.conf`:

```properties
# Enable Python UDF support
enable_python_udf_support = true

# Choose environment management mode (conda or venv)
python_env_mode = conda

# For Conda mode
python_conda_root_path = /path/to/miniconda3

# For venv mode
python_env_mode = venv
python_venv_root_path = /doris/python_envs
python_venv_interpreter_paths = /opt/python3.9/bin/python3.9:/opt/python3.12/bin/python3.12

# Process pool size (0 = use CPU core count)
max_python_process_num = 0
```

## Technical Highlights

### 1. Environment Management
- **Multi-version support**: Each UDF can specify its own Python version
- **Two modes**: Conda (full environment isolation) or venv
(lightweight)
- **Automatic discovery**: Scans available Python environments at BE
startup

### 2. Process Pool Management
- **Shared pool**: One pool per Python version, shared across all
threads
- **Load balancing**: Distributes requests to processes with minimum
load
- **Health monitoring**: Background thread checks process health every
60 seconds
- **Auto recovery**: Automatically recreates dead processes

### 3. Communication Protocol
- **Arrow Flight RPC**: High-performance, language-agnostic RPC
framework
- **Unix Socket**: Local IPC for minimal latency and enhanced security
- **Bidirectional streaming**: Efficient batch data transfer

### 4. Execution Modes
- **Scalar mode**: Process one value at a time (simple functions)
- **Vectorized mode**: Process entire columns with NumPy/Pandas (10-100x
faster)
- **Adaptive selection**: Automatically chooses mode based on function
signature

### 5. UDAF State Management (Snowflake Style)
- **5 lifecycle methods**: `__init__`, `accumulate`, `merge`, `finish`,
`aggregate_state`
- **Distributed aggregation**: Serialization/deserialization for shuffle
operations
- **Efficient state handling**: Place-based mapping avoids redundant
transfers

## Limitations

1. **Performance**: Python UDFs are slower than native C++ built-in
functions. Best suited for complex logic that's difficult to implement
in SQL.
2. **Type support**: Special Doris types like HLL and Bitmap are not yet
supported.
3. **Concurrency**: Parallelism is limited by `max_python_process_num`
setting.

## Related Documentation

- Python UDF User Guide
- Python UDAF User Guide
- Python UDTF User Guide
- Python Environment Configuration Guide

---

**This PR enables users to leverage the rich Python ecosystem (NumPy,
Pandas, scikit-learn, etc.) directly within Doris SQL queries,
significantly expanding the platform's data processing capabilities.**


### Check List (For Author)

- Test <!-- At least one of them must be included. -->
    - [ ] Regression test
    - [ ] Unit Test
    - [ ] Manual test (add detailed scripts or steps below)
    - [ ] No need to test or manual test. Explain why:
- [ ] This is a refactor/code format and no logic has been changed.
        - [ ] Previous test can cover this change.
        - [ ] No code files have been changed.
        - [ ] Other reason <!-- Add your reason?  -->

- Behavior changed:
    - [ ] No.
    - [ ] Yes. <!-- Explain the behavior change -->

- Does this need documentation?
    - [ ] No.
- [ ] Yes. <!-- Add document PR link here. eg:
https://github.com/apache/doris-website/pull/1214 -->

### Check List (For Reviewer who merge this PR)

- [ ] Confirm the release note
- [ ] Confirm test cases
- [ ] Confirm document
- [ ] Add branch pick label <!-- Add branch pick label that this PR
should merge into -->

---------

Co-authored-by: yangshijie <jasonsjyang@tencent.com>
2026-01-30 10:37:03 +08:00

113 lines
1.5 KiB
Plaintext

-- This file is automatically generated. You should know what you did if you want to edit this
-- !select_1 --
1 10 1000 1010
2 20 2000 2020
3 30 3000 3030
4 40 4000 4040
5 50 5000 5050
-- !select_2 --
1 100 1000 1100
2 200 2000 2200
3 300 3000 3300
4 400 4000 4400
5 500 5000 5500
-- !select_3 --
1 1000 10000 11000
2 2000 20000 22000
3 3000 30000 33000
4 4000 40000 44000
5 5000 50000 55000
-- !select_4 --
1 1.5 10.5 12
2 2.5 20.5 23
3 3.5 30.5 34
4 4.5 40.5 45
5 5.5 50.5 56
-- !select_5 --
1 10 100 1000 1110
2 20 200 2000 2220
3 30 300 3000 3330
4 40 400 4000 4440
5 50 500 5000 5550
-- !select_6 --
1 10 100 1000
2 20 200 4000
3 30 300 9000
4 40 400 16000
5 50 500 25000
-- !select_7 --
1 1.5 10.5 7
2 2.5 20.5 8.199999999999999
3 3.5 30.5 8.714285714285714
4 4.5 40.5 9
5 5.5 50.5 9.181818181818182
-- !select_8 --
1 1000 1.5 2001.5
2 2000 2.5 4002.5
3 3000 3.5 6003.5
4 4000 4.5 8004.5
5 5000 5.5 10005.5
-- !select_9 --
1 test1 TEST1
2 test2 TEST2
3 test3 TEST3
4 test4 TEST4
5 test5 TEST5
-- !select_10 --
1 true false
2 false true
3 true false
4 false true
5 true false
-- !select_11 --
1 10 10000 10010
2 20 20000 20020
3 30 30000 30030
4 40 40000 40040
5 50 50000 50050
-- !select_12 --
1 1000 1500
2 2000 3000
3 3000 4500
4 4000 6000
5 5000 7500
-- !select_13 --
1 test1 \N
-- !select_14 --
1 10000 11000
-- !select_15 --
1 10.5 12.0
-- !select_16 --
1 true 1001
-- !select_17 --
1 2024-01-01 2024-01-01
-- !select_18 --
1 1000 false
-- !select_19 --
1 test1 \N
-- !select_20 --
1 test1 true \N
-- !select_22 --
1 1.5 1001