SQLite Data Accelerator
To use SQLite as Data Accelerator, specify sqlite as the engine for acceleration.
datasets:
- from: spice.ai:path.to.my_dataset
name: my_dataset
acceleration:
engine: sqlite
Configuration​
The connection to SQLite can be configured by providing the following params:
sqlite_file: The filename for the file to back the SQLite database. Only applies ifmodeisfile.busy_timeout: Optional. Specifies the duration for the SQLite busy timeout when connecting to the database file. Default: 5000 ms, or 15000 ms when the accelerationstorage_profileresolves to EBS-class network storage (where fsync latency spikes are more frequent).
Configuration params are provided in the acceleration section of a dataset. Other common acceleration fields can be configured for sqlite, see see datasets.
datasets:
- from: spice.ai:path.to.my_dataset
name: my_dataset
acceleration:
engine: sqlite
mode: file
params:
sqlite_file: /my/chosen/location/sqlite.db
- The SQLite accelerator doesn't support arrow
Intervaltypes, as SQLite doesn't have a native interval type. - The SQLite accelerator only supports arrow
Listtypes of primitive data types; lists with structs are not supported. - The SQLite accelerator doesn't support
DictionaryorMaptypes. - SQLite may not be suitable for high row count use cases with complex join queries. Use DuckDB instead.
ROLLUP,CUBE, andGROUPING SETSare evaluated in Spice, not in SQLite, because SQLite has no grouping sets.TRY_CASTis never sent to SQLite, and aCASTis sent only when SQLite evaluates it the same way Spice does. See Casts and Federation.AVGandSUMover a decimal column are never sent to SQLite. SQLite stores a decimal value as a double, so a value with more than about 15 significant digits reads back changed. See Decimal Aggregates and Federation.upper,lower,concat,LIKE, andILIKEare evaluated in Spice, not in SQLite, because SQLite answers them differently. Several functions SQLite does not have, such asbtrimandmd5, and every aggregate exceptcount,sum,avg,min, andmax, are also evaluated in Spice. See Functions and Federation.- Updating a dataset with SQLite acceleration while the Spice Runtime is running (hot-reload) will cause SQLite accelerator query federation to disable until the Runtime is restarted.
When accelerating a dataset using mode: memory (the default), some or all of the dataset is loaded into memory. Ensure sufficient memory is available, including overhead for queries and the runtime, especially with concurrent queries.
In-memory limitations can be mitigated by storing acceleration data on disk, which is supported by duckdb and sqlite accelerators by specifying mode: file.
Casts and Federation​
SQLite's CAST never fails. A cast into a numeric type converts the longest numeric prefix of its operand and returns 0 when there is none, so CAST('abc' AS BIGINT) returns 0 and CAST('12abc' AS BIGINT) returns 12 (see CAST expressions in the SQLite documentation). SQLite also formats floats and booleans as text differently, stores dates and timestamps in its own representation, and has no TRY_CAST. To return the same results as an unaccelerated query, Spice sends a cast to the SQLite accelerator only when SQLite evaluates it the same way:
- A cast between two string types, or between two binary types.
- An integer cast into a wider integer type, into
Float64, or into text. - A
Float32cast intoFloat64. - A string literal cast into a date when the literal is already written as
YYYY-MM-DD, such asDATE '1994-01-01'.
Every other CAST, and every TRY_CAST, is evaluated in Spice above the scan of the accelerated table. This includes a cast whose operand type Spice cannot determine. For example, CAST(s AS BIGINT) over a string column that holds 'abc' returns the error a DataFusion query returns, not 0, and CAST(1 AS DECIMAL) / CAST(2 AS DECIMAL) returns 0.5, not the result of SQLite integer division. A query whose plan contains such a cast still runs, but that cast does not push down to SQLite.
Decimal Aggregates and Federation​
SQLite has no decimal type. It stores a decimal value as a REAL or an INTEGER, and computes avg and sum over it in floating point or in 64-bit integers. Its avg returns a rounded floating-point value where Spice computes the average in decimal arithmetic and truncates it to the scale of the result type. Its sum over values stored as integers fails with an integer overflow once the total exceeds the 64-bit integer range, and a sum that includes a value stored as a REAL is computed in floating point instead.
So that these aggregates follow Spice's decimal semantics, Spice does not send AVG or SUM over a decimal column to the SQLite accelerator, whether called as an aggregate or as a window function. The aggregate is evaluated in Spice above the scan of the accelerated table, and the scan is still sent to SQLite with its filters and projection, except for any expression Spice keeps local, such as the casts in Casts and Federation. An aggregate whose argument type Spice cannot determine is also evaluated in Spice. Aggregates over integer and floating-point columns, and other aggregates over decimal columns such as MIN, MAX, and COUNT, are still sent to SQLite.
This changes where the aggregate runs, not how SQLite stores the values. SQLite stores a decimal value as a double, so a value with more than about 15 significant digits is rounded when it is written and reads back changed, with no error (spiceai/spiceai#14662). An aggregate evaluated in Spice is exact over the values SQLite returns, so over such values it can still differ from an unaccelerated query. In the reproduction on that issue, the arrow and duckdb accelerators return such a value unchanged.
Functions and Federation​
Spice keeps the following functions and expressions out of the SQL sent to the SQLite accelerator, because SQLite does not have them or answers them differently. Each is evaluated in Spice above the scan of the accelerated table, over the values SQLite returns. This changes where the expression runs, not how SQLite stores the data, so a decimal value that SQLite rounded on write still reads back changed, as described in Decimal Aggregates and Federation:
upperandlower. SQLite changes the case of ASCII letters only, soupper('Ångström')returns'ÅNGSTRöM'in SQLite and'ÅNGSTRÖM'in Spice.concat. SQLite'sconcatskips aNULLargument, while Spice'sconcatreturnsNULLwhen any argument isNULL.LIKEandILIKE. SQLite'sLIKEignores the case of ASCII letters, so'alice' LIKE '%ALICE%'is true in SQLite and false in Spice. SQLite has noILIKE.btrim(includingtrim),to_hex,md5,sha256,encode,date_part(includingEXTRACT),date_trunc,regexp_like,regexp_replace,regexp_match,regexp_instr, andregexp_count, which SQLite does not have or answers differently.- Every aggregate except
count,sum,avg,min, andmax, and any aggregate call with more than one argument, such ascount(a, b). This includesstring_agg,array_agg,stddev,median, andapprox_distinct. - Window functions other than SQLite's own (
row_number,rank,dense_rank,percent_rank,cume_dist,ntile,lag,lead,first_value,last_value, andnth_value) and the five aggregates above, a window function withDISTINCT, and an aggregate or window function withIGNORE NULLS.
These rules add to the checks Spice applies to every federated source, which already keep Spice-defined and user-registered functions, DataFusion's cast functions such as arrow_cast, and type functions such as arrow_typeof in Spice. A DataFusion built-in scalar function that passes those checks and is not listed above is sent to SQLite by name. The list covers the functions Spice is known to evaluate differently from SQLite; it is not a check of every function against SQLite.
Cookbook​
- A cookbook recipe to configure SQLite as a data accelerator in Spice. SQLite Data Accelerator
