Changes for version 0.22 - 2026-10-16
- Faster hot paths. Client CPU per query against MariaDB / Pg: insert -18% / -15%, update -16% / -6%, reads -2% to -9%. SQLite in memory (the library's own cost): update -32%, insert -28%, delete -27%, val -23%, upsert -19%, hash -16%. Same on perl 5.40 and 5.44; see dev/benchmarks-0.21-0.22.md. DBIx::Fast now adds ~2 us of CPU per query over plain DBI with a prepared handle (~11 us on MariaDB/Pg):
- the SQL role keeps the connector in a field (no accessor call)
- separate caches for consumed handles (no FETCH('Active') per call) and for handles given to the caller (query/exec/ execute_prepare keep the check)
- Connector::dbh checks Active every 100 calls; any DB error and any disconnect() on the handle force the check on the next call (the time-based ping check still runs on every call)
- CRUD writes: inline execute path; a cached, validated column set with plain values is not revalidated (never for names holding the cache key's NUL separator); last_id read inline
- compile_val / compile_hash / compile_all / compile_insert: prepared operations for loops (compile_insert about half the time of insert)
- Fix: rare SIGSEGV at exit (a few % of runs, seen with DBD::SQLite): the statement cache (0.20) lives outside the DBI handle, so global destruction could free a cached statement after its connection and DBD::SQLite finalized it on a closed db. An END block now drops the cached statements while the connections are open
- on_slow_query: the report carries caller ("file:line" of the application code that ran the statement)
- on_slow_query => { explain => 1 }: the plan of a slow SELECT in $q->{explain} (EXPLAIN / EXPLAIN QUERY PLAN on the same handle; skipped with a result set open, inside a Pg transaction, and on Pg with redact)
- on_slow_query => { redact => 0 | 1 | sub ($sql, @binds) {...} }: its own bind masking (defaults to errors_redact as before)
- page(..., count => 'window'): the total with COUNT(*) OVER () in the page query, one pass instead of two (LIKE '%x%' ordered by an unindexed column, 200k rows: MariaDB 226 -> 114 ms, Pg 68 -> 33 ms)
- count_by($table, $column, \%where): { value => rows } with one GROUP BY instead of a count() per value
- sql_stats => 1 | N: executions, total and max time per statement (placeholder lists collapsed: IN (?, ...), multi-row VALUES), bounded (500 distinct by default, the rest under "(other)"); sql_stats(top, order), reset_sql_stats()
- scope_start / scope_end: per-statement counts of a unit of work (a request, a job); on_repeated_query => { n, cb } fires when one statement runs n times in a scope (N+1), with the caller of the n-th run
- Slow-statement reporting moved out of the per-statement observer (fewer fields bound per observed statement)
- DBIx::Fast->metrics_merge(@texts): one Prometheus exposition from several workers' metrics_text (documented recipe for preforking servers, where a scrape reaches a single worker)
- Docs: metrics/on_slow_query cost ~3 us per statement (timing + no cached-statement fast path), not 1-1.5 us
Modules
DBI fast & easy
Base class for DBIx::Fast components
Query result cache with TTL and tag invalidation
Redis backend for DBIx::Fast's result cache
Query proxy that caches results
DBIx::Fast connection manager fork safe
Unified output layer for the profiler subsystem
Abstract base class for database driver profiles
MariaDB/MySQL profiling and diagnostics
PostgreSQL profiling and diagnostics
SQLite profiling stub
MySQL profiling and diagnostics
Query profiling and statistics for DBIx::Fast
Lightweight row iterator for query results
Query and CRUD methods of DBIx::Fast
Schema introspection for DBIx::Fast
a DBIx::Fast with canned answers, for unit tests
Transaction management for DBIx::Fast
Typed exceptions for DBIx::Fast
Examples
- examples/README.md
- examples/benchmark-cache-backends.pl
- examples/benchmark-json.pl
- examples/benchmark-lazy-require.pl
- examples/benchmark-profiler-regex.pl
- examples/benchmark-query-cache.pl
- examples/benchmark-statement-cache.pl
- examples/errors-and-reads.pl
- examples/monitor-connections.pl
- examples/profiler-mariadb.pl
- examples/profiler-pg.pl
- examples/raw-sql.pl