Xqlite.ExplainAnalyze (Xqlite v0.7.0)
View SourceStructured report from Xqlite.explain_analyze/3.
Combines SQLite's static plan (EXPLAIN QUERY PLAN) with runtime stats
collected via sqlite3_stmt_scanstatus_v2 and sqlite3_stmt_status, plus
a wall-clock timer around the execution.
Fields
:wall_time_ns— nanoseconds the statement spent insidesqlite3_step, measured withstd::time::Instanton the Rust side.:rows_produced— how many rows the statement returned. Always 0 for DML withoutRETURNING.:stmt_counters— statement-level counters. Seesqlite3_stmt_status. Notable entries::fullscan_step— rows iterated via full-table scan, index included. Non-zero generally means a missing index.:vm_step— total VDBE instructions executed.:sort— rows sorted byORDER BY/GROUP BY.:memused_bytes— peak memory used by the statement.
:scans— per-loop runtime stats. One entry per scan node in the executed plan. Keys per entry::loops,:rows_visited,:estimated_rows,:name,:explain,:selectid,:parentid. A big gap between:rows_visitedand:estimated_rowshints at staleANALYZEdata or a mis-estimated join.:query_plan— rows fromEXPLAIN QUERY PLAN. One entry per plan node, with:id,:parent, and:detail(the human-readable "SCAN table" / "SEARCH table USING INDEX ..." line).
SQLite has no per-operator wall time
Postgres's EXPLAIN (ANALYZE) attributes wall time to every plan node.
SQLite does not. We report a whole-statement wall time plus per-loop row
counts and estimates, and you infer hot spots from the combination.
Summary
Functions
Converts the raw NIF report map into an %Xqlite.ExplainAnalyze{} struct.
Types
@type scan() :: %{ loops: non_neg_integer(), rows_visited: non_neg_integer(), estimated_rows: float(), name: String.t(), explain: String.t(), selectid: integer(), parentid: integer() }
@type t() :: %Xqlite.ExplainAnalyze{ query_plan: [query_plan_row()], rows_produced: non_neg_integer(), scans: [scan()], stmt_counters: stmt_counters(), wall_time_ns: non_neg_integer() }