Orchestration
How to run LLM calls over millions of rows
Running language-model calls over millions of rows is a cache and scheduling problem. A Python loop that restarts from row zero will re-pay every token. A batch engine such as Spark, Ray Data, or Daft scans a lake once. A computed column caches each row and recomputes only rows that changed.
Updated · Part of What is incremental computation?
Short answer
Do not wrap the model client in a for-loop you restart. Persist each result next to its source row. On the next run, skip rows whose inputs have not changed. A batch engine (Spark, Ray Data, Daft) is the right tool for a one-shot scan over a lake. A computed column is the right tool for a live table: insert recomputes that row; unchanged rows keep the cache. This page quotes no tokens-per-second and no dollar totals.
Why a restartable loop fails
A script that embeds or summarizes every path in a folder looks fine until it dies at row 400,000 and you run it again. Without a stored result keyed by content (or by a declared dependency), you pay the model vendor a second time for work you already bought. Rate limits and partial failure make that worse. The fix is a cache with lineage, not a longer sleep().
A lake scan versus a live table
Pick the engine from the data shape.
- Lake scan: Ray Data streams CPU preprocess into GPU or API inference (https://docs.ray.io/en/latest/data/data.html). Daft is a multimodal dataframe (https://docs.daft.ai/en/stable/). Spark is a unified analytics engine (https://spark.apache.org/docs/latest/). Write the sink so a rerun can skip completed keys if you add that logic.
- Live table: declare the LLM call as a column. Insert or edit a row and that expression runs. Unchanged rows stay cached. Editing a prompt recomputes the columns that depend on it. Docs: computed columns in Related.
How to choose
This is not a bake-off. It is a fit check.
- Historical dump in a lake, run once or on a schedule: Spark, Ray Data, or Daft.
- New files arriving as application rows: a computed column.
- Both: backfill with a batch engine, then serve new rows from a table.
Last reviewed
Facts on this page were checked against vendor documentation on 2026-10-28. Product surfaces move; treat version names and APIs as directional and follow the official links in Related.
Ways to run LLM calls over a large table (last reviewed: Oct 2026)
| Approach | What reruns | Cache | Fit |
|---|---|---|---|
| Python for-loop | Whatever the script reads after a restart | Only if you write one | Prototypes. Not millions of rows |
| Spark / Ray Data / Daft job | The job you launch; skip logic is yours | The sink you write | A lake scan or a scheduled backfill |
| Hosted batch API | The vendor job | Vendor-dependent | When you do not want to run the cluster |
| Computed column | New or changed rows, and dependents of a prompt edit | Per row, with lineage | A live table that receives inserts |
Where Pixeltable fits
Use Pixeltable when the millions of rows are a live table: assign chat_completions on the class so each new or changed row runs, then caches. It is not a Spark-shaped scan over a lake. For that backfill, keep Ray Data, Daft, or Spark and load the result. How-to: add computed columns with LLM calls in Python. What is incremental computation? covers the cache rule. This page does not publish a tokens-per-second number.
import pixeltable as pxtfrom pixeltable.functions.openai import chat_completionsTableModel = pxt.model_base()class Docs(TableModel, name='docs'):text: pxt.Stringsource: pxt.Stringsummary = chat_completions(messages=[{'role': 'user', 'content': text}],model='gpt-4o-mini',).choices[0].message.content# pxt schema update app.py docs -f# Insert new or changed rows. Unchanged rows keep the cached summary.# Do not wrap chat_completions in a Python for-loop over the table.
Questions
Does every insert re-call the model for old rows?
Should I use Spark instead of a computed column?
How do I avoid paying twice for the same prompt?
Will this page quote a cost for one million rows?
Next step
Install the Pixeltable skill, or sign up for Cloud and run the same file on a hosted database.