From 41436cfa1d61505aba666429139a21caef82b5b1 Mon Sep 17 00:00:00 2001 From: hussainsultan Date: Fri, 31 Jan 2025 17:29:31 -0500 Subject: [PATCH] docs: add udf rewriting blog post --- .../udf-rewriting/images/tree-pruning.png | Bin 0 -> 84300 bytes docs/posts/udf-rewriting/index.qmd | 346 ++++++++++++++++++ 2 files changed, 346 insertions(+) create mode 100644 docs/posts/udf-rewriting/images/tree-pruning.png create mode 100644 docs/posts/udf-rewriting/index.qmd diff --git a/docs/posts/udf-rewriting/images/tree-pruning.png b/docs/posts/udf-rewriting/images/tree-pruning.png new file mode 100644 index 0000000000000000000000000000000000000000..fb92063ead559e663ebf09f4b536cd1238a1e884 GIT binary patch literal 84300 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 spvE7=_ca8l14?Cf1LjV8( literal 0 HcmV?d00001 diff --git a/docs/posts/udf-rewriting/index.qmd b/docs/posts/udf-rewriting/index.qmd new file mode 100644 index 000000000000..6e8c2f612797 --- /dev/null +++ b/docs/posts/udf-rewriting/index.qmd @@ -0,0 +1,346 @@ +--- +title: "Dynamic UDF Rewriting with Predicate Pushdowns" +author: "Hussain Sultan" +date: "2025-01-31" +categories: + - blog + - case study + - machine learning + - ecosystem +--- + +## Introduction + +In an ideal world, deploying machine learning models within SQL queries would be as simple as calling a built-in function. Unfortunately, many ML predictions live inside **User-Defined Functions (UDFs)** that traditional SQL optimizers treat as black boxes. This effectively prevents advanced optimizations like predicate pushdown, leading to significant performance overhead when running large-scale inference. + +In this blog post, we’ll showcase how you can **prune decision tree models based on query filters** by dynamically rewriting your UDF using **Ibis** and **quickgrove**,an experimental XGBoost inference library built in Rust. We'll also show how [LetSQL](https://github.com/letsql/letsql) can simplify this pattern further and integrate seamlessly into your ML workflows. + +--- + +## The Challenge: ML Models Meet SQL + +When you deploy machine learning models (like a gradient-boosted trees model from XGBoost) in a data warehouse, you typically wrap them in a UDF. Something like: + +```sql +SELECT + my_udf_predict(carat, depth, color, clarity, ...) +FROM diamonds +WHERE color_i < 1 AND clarity_vvs2 < 1 +``` + +The problem is that **SQL optimizers don’t know what’s happening inside the UDF**. Even if you filter `color_i < 1`, the full model itself is still evaluated for every row meeting the filter condition. With tree-based models, however, entire branches might never be evaluated at all if they exceed certain thresholds—so the ideal scenario is to prune those unnecessary branches *before* evaluating them. + +### Why It Matters + +- **Flexible:** Ibis provides a user-facing IR that's transparent and easy to manipulate and rewrite +- **Simple**: Add advanced techniques e.g. predicate pushdowns in your pipeline without having to dive into database internals +- **Performant**: For large datasets (hundreds of millions of rows or more), these optimizations add up quickly. + +--- + +## The Solution: Smart UDFs with Ibis + +**Ibis** is known for letting you write queries in Python without losing the power of underlying engines like Spark, DuckDB, or BigQuery. Meanwhile, quickgrove provides a mechanism to prune gradient-boosted decision trees based on known filter conditions for pruning Gradient Boosted Decision Tree (GBDT) models. + +**Key Ideas**: + +1. **Create UDFs that are predicate-aware** — So we can rewrite them if the upstream query includes filters. +2. **Prune decision trees** — Removing branches that can never be reached, given the known filters. +3. **Inject the pruned model** back into your query plan to skip unnecessary computations. + +### Understanding Tree Pruning + +![Tree Pruning](images/tree-pruning.png) + +Take a simple example: a decision tree that splits on `x < 0.3`. If your query also has a predicate `x < 0.2`, any branches assuming `x >= 0.3` will never be evaluated. By **removing** that branch, the tree becomes smaller and faster to evaluate—especially when you have hundreds of trees (as in many gradient-boosted models). + +**Reference**: Check out the [Raven optimizer](https://arxiv.org/pdf/2206.00136) paper. It demonstrates how you can prune nodes in query plans for tree-based inference, so we’re taking a similar approach here for **forests** (GBDTs) using **Ibis.** + +--- + +### Enter quickgrove: Prune-able GBM Models + +Quickgrove is an experimental package that can loads XGBoost JSON models and provides a `.prune(...)` API to remove unreachable branches. For example: + +```python +#pip install quickgrove +import quickgrove + +model = quickgrove.json_load("diamonds_model.json") # Load an XGBoost model +model.prune([quickgrove.Feature("carat") < 0.2]) # Prune based on known predicate +``` + +Once pruned, the model is leaner to evaluate but the results heavily depends on the the model and how the predicates interact with the trees within the model. + +--- + +## Scalar PyArrow UDFs in Ibis + +::: {.column-margin} +Please note that we are using the DataFusion backend. DataFusion backend and DuckDB backends behave differently in that DuckDB expects a `ChunkedArray` while DataFusion UDFs expect `ArrayRef`. This case needs to be handled if we want the same UDF to run in DuckDB backend. +::: + +We’ll define a simple Ibis UDF that calls our `model.predict_arrays` under the hood: + +```python +import ibis +import ibis.expr.datatypes as dt + +ibis.set_backend("datafusion") +@ibis.udf.scalar.pyarrow +def predict_gbdt( + carat: dt.float64, + depth: dt.float64, + # ... other features ... +) -> dt.float32: + array_list = [carat, depth, ...] + return model.predict_arrays(array_list +``` + +In its default form, `predict_gbdt` is a black box. Now we need Ibis to “understand” it enough to let us swap it out for a pruned version under the right conditions. + +--- + +## Making Ibis Predicate-Aware + +Here’s the general process: + +1. **Collect predicates** from the user’s filter (e.g. `x < 0.3`). +2. **Prune** the model based on those predicates (removing unreachable tree branches). +3. **Inject** a new UDF that references the pruned model, preserving the rest of the query plan. + +### 1. Collecting Predicates + +```python +from ibis.expr.operations import Filter, Less, Field, Literal +from typing import List, Dict + +def collect_predicates(filter_op: Filter) -> List[dict]: + """Extract 'column < value' predicates from a Filter operation.""" + predicates = [] + for pred in filter_op.predicates: + if isinstance(pred, Less) and isinstance(pred.left, Field): + if isinstance(pred.right, Literal): + predicates.append({ + "column": pred.left.name, + "op": "Less", + "value": pred.right.value + }) + return predicates +``` + +### 2. Pruning the Model & Creating a New UDF + +```python +import functools +from ibis.expr.operations import ScalarUDF +from ibis.util import FrozenDict + +def create_pruned_udf(original_udf, model, predicates): + """Create a new UDF using the pruned model based on the collected predicates.""" + from quickgrove import Feature + + # Prune the model + pruned_model = model.prune([ + Feature(pred["column"]) < pred["value"] + for pred in predicates + if pred["op"] == "Less" and pred["value"] is not None + ]) + # For simplicity, let’s assume we know the relevant features or keep them the same. + + def fn_from_arrays(*arrays): + return pruned_model.predict_arrays(list(arrays)) + + # Construct a dynamic UDF class + meta = { + "dtype": dt.float32, + "__input_type__": "pyarrow", + "__func__": property(lambda self: fn_from_arrays), + "__config__": FrozenDict(volatility="immutable"), + "__udf_namespace__": original_udf.__module_ + "__module__": original_udf.__module__, + "__func_name__": original_udf.__name__ + "_pruned" + } + + # Create a new ScalarUDF node type on the fly + node = type(original_udf.__name__ + "_pruned", (ScalarUDF,), {**fields, **meta}) + + @functools.wraps(fn_from_arrays) + def construct(*args, **kwargs): + return node(*args, **kwargs).to_expr() + + construct.fn = fn_from_arrays + return construct +``` + +### 3. Rewriting the Plan + +Now we use an Ibis rewrite rule (or a custom function) to **detect filters** on the expression, prune the model, and produce a new project/filter node. + +```python +from ibis.expr.operations import Project + +def prune_gbdt_model(filter_op, original_udf, model): + """Rewrite rule to prune GBDT model based on filter predicates.""" + + predicates = collect_predicates(filter_op) + if not predicates: + # Nothing to prune if no relevant predicates + return filter_op + + pruned_udf, required_features = create_pruned_udf(original_udf, model, predicates) + + parent_op = filter_op.parent + # Build a new projection with the pruned UDF + new_values = {} + for name, value in parent_op.values.items(): + # If it’s the column that calls the UDF, swap with pruned version + if name == "prediction": + # For brevity, assume we pass the same columns to the pruned UDF + new_values[name] = pruned_udf(value.op().args[0], value.op().args[1]) + else: + new_values[name] = value + + new_project = Project(parent_op.parent, new_values) + + # Re-add the filter conditions on top + new_predicates = [] + for pred in filter_op.predicates: + if isinstance(pred, Less) and isinstance(pred.left, Field): + new_predicates.append( + Less(Field(new_project, pred.left.name), pred.right) + ) + else: + new_predicates.append(pred) + + return Filter(parent=new_project, predicates=new_predicates) +``` + +## Diff + +The following columns were removes from the function signature since they are no longer required in the pruned version of the mode. + +Notice that with pruning we are also able to drop some of the projections in the UDF i.e. `color_i`, `color_j` and `clarity_vvs2`. The underlying engine .e.g. DataFusion may optimize this further when pulling data for UDFs. We cannot completely drop these from the query expression. + +```python +- predict_gbdt_3( ++ predict_gbdt_pruned( + carat, depth, table, x, y, z, + cut_good, cut_ideal, cut_premium, cut_very_good, + color_e, color_f, color_g, color_h, color_i, color_j, + clarity_if, clarity_si1, clarity_si2, clarity_vs1, +- clarity_vs2, clarity_vvs1, clarity_vvs2 ++ clarity_vs2, clarity_vvs1 +) +``` + +> Note: The above is a conceptual example. In a real implementation, you’ll wire this into a full Ibis rewrite pass so it automatically triggers whenever relevant filters are present in your query expression. +> + +--- + +## Putting It All Together + +The complete example can be found here: https://github.com/letsql/trusty/blob/main/python/examples/ibis_filter_condition.py + +```python +# 1. Load your dataset into Ibis +t = ibis.read_csv("diamonds_data.csv") + +expr = ( + t.mutate(prediction=predict_gbdt(t.carat, t.depth, ...)) + .filter( + (t["clarity_vvs2"] < 1), + (t["color_i"] < 1), + (t["color_j"] < 1) + ) + .select("prediction") +) + +# 3. Apply your custom optimization +optimized_expr = prune_gbdt_model(expr.op(), predict_gbdt, model) + +# 4. Execute the optimized query +result = optimized_expr.to_expr().execute() +``` + +When this is done, the model inside `predict_gbdt` will be **pruned** based on your filter conditions. On large datasets, this can yield significant speedups. + +--- + +## Performance Impact + +[Here](https://github.com/letsql/quickgrove/blob/main/python/examples/ibis_filter_condition_bench.py) is the benchmark results ran on Apple M2 Mac Mini, 8 cores / 8GB Memory run with a model trained with 100 trees and depth 6 with following filter conditions: + +``` +_.carat < 1, +_.clarity_vvs2 < 1, +_.color_i < 1, +_.color_j < 1, +``` + +Benchmark results: + +| File Size | Regular (s) | Optimized (s) | Improvement | +| --- | --- | --- | --- | +| 5M | 0.82 ±0.02 | 0.67 ±0.02 | 18.0% | +| 25M | 4.16 ±0.01 | 3.46 ±0.05 | 16.7% | +| 100M | 16.80 ±0.17 | 14.07 ±0.11 | 16.3% | + +**Key takeaway**: As data volume grows, skipping unneeded tree branches can translate to real savings in both time and compute cost, albeit heavily dependent on how pertinent the filter conditions might be. + +--- + +## LetSQL: Simplifying UD(X)Fs + +**[LetSQL](https://letsql.com/)) makes advanced UDF rewriting and multi-engine pipelines much simpler. It builds on the same ideas we explored here but wraps them in a higher-level API. + +Here’s a quick glimpse of how LetSQL might simplify the pattern: + +```python +# pip install letsql + +import letsql as ls +from letsql.expr.ml import make_quickgrove_udf, rewrite_quickgrove_expression + +model_path = "xgboost_model.json" +predict_udf = make_quickgrove_udf(model_path) + +t = ls.memtable(df).mutate(pred=predict_udf.on_expr).filter(ls._.carat < 1) +optimized_t = rewrite_quickgrove_expression(t) + +result = ls.execute(optimized_t) +``` + +With LetSQL, you get a **shorter, more declarative approach** to the same optimization logic we manually coded with Ibis. It abstracts away the gritty parts of rewriting your query plan. + +--- + +## Best Practices & Considerations + +- **Predicate Types**: Currently, we demonstrated `column < value` logic. You can extend it to handle `<=`, `>`, `BETWEEN`, or even categorical splits. +- Quickgrove only supports a handful of objective functions and most notably does not have categorical support yet. In theory, categorical variables make a better candidates for pruning based on filter conditions. +- **Model Format**: XGBoost JSON is straightforward to parse. Other formats (e.g. LightGBM, scikit-learn trees) require similar logic or conversion steps. +- **Edge Cases**: If the filter references columns not in the model features, or if multiple filters combine in more complex ways, your rewriting logic may need more robust parsing. +- **When to Use**: This approach is beneficial when queries often filter on the same columns your trees split on. For purely ad-hoc queries or rarely used filters, the overhead of rewriting might outweigh the benefit. + +--- + +## Conclusion + +Combining **Ibis** with a prune-friendly framework like quickgrove lets you automatically optimize large-scale ML inference inside SQL queries. By **pushing filter predicates down into your decision trees**, you skip unnecessary computations and speed up queries significantly. + +**And with LetSQL**, you can streamline this entire process—especially if you’re looking for an out-of-the-box solution that integrates with multiple engines and query languages. As next steps, consider experimenting with more complex models, exploring different tree pruning strategies, or even extending this pattern to other ML models beyond GBDTs. + +- **Try it out**: Explore the Ibis documentation to learn how to build custom UDFs. +- **Dive deeper**: Check out [quickgrove](https://github.com/letsql/trusty) or read the Raven optimizer [paper](https://arxiv.org/pdf/2206.00136). +- **Experiment with LetSQL**: If you need a polished solution for dynamic ML UDF rewriting, [LetSQL](https://github.com/letsql/letsql) may be just the ticket. + +--- + +## Resources + +- **Paper**: [End-to-end Optimization of Machine Learning Prediction Queries (Raven)](https://arxiv.org/pdf/2206.00136) +- **Ibis + Torch**: [Ibis Project Blog Post](https://ibis-project.org/posts/torch/) +- **quickgrove**: [GitHub Repository](https://github.com/letsql/quickgrove) +- **LetSQL**: [Documentation](https://docs.letsql.com)