DuckDB query profiling helpers.
analyze/4 runs EXPLAIN (ANALYZE, FORMAT json) and decodes DuckDB's
profile with Elixir's built-in JSON.decode/3. Known DuckDB profile keys are
decoded with String.to_existing_atom/1 and loaded into structs. DuckDB's
open-ended extra_info maps keep their own keys.
Use flatten/1, slowest/2, and report/2 when you want a profiler-style
operator view.
Summary
Functions
Runs EXPLAIN (ANALYZE, FORMAT json) and returns a decoded DuckDB query profile.
Runs EXPLAIN (ANALYZE, FORMAT json) and returns a decoded DuckDB query profile, raising on errors.
Runs EXPLAIN (FORMAT json) and returns a decoded DuckDB plan profile.
Runs EXPLAIN (FORMAT json) and returns a decoded DuckDB plan profile, raising on errors.
Converts DuckDB's profile tree into profiler-style operator rows.
Formats a compact text report for humans.
Returns the slowest operators by operator_timing.
Types
@type operator_row() :: %{ path: [non_neg_integer()], name: String.t() | nil, type: String.t() | nil, timing: number() | nil, timing_percent: float() | nil, cpu_time: number() | nil, cardinality: non_neg_integer() | nil, rows_scanned: non_neg_integer() | nil, cumulative_cardinality: non_neg_integer() | nil, cumulative_rows_scanned: non_neg_integer() | nil, result_set_size: non_neg_integer() | nil, extra_info: map() }
A flattened DuckDB operator row with its tree path and timing share.
@type t() :: %QuackDB.Profile{ all_optimizers: term(), attach_load_storage_latency: term(), attach_replay_wal_latency: term(), blocked_thread_time: term(), checkpoint_latency: term(), children: [QuackDB.Profile.Operator.t()], commit_local_storage_latency: term(), cpu_time: number() | nil, cumulative_cardinality: non_neg_integer() | nil, cumulative_optimizer_timing: term(), cumulative_rows_scanned: non_neg_integer() | nil, extra_info: term(), latency: number() | nil, optimizers: map(), physical_planner: term(), physical_planner_column_binding: term(), physical_planner_create_plan: term(), physical_planner_resolve_types: term(), planner: term(), planner_binding: term(), query_name: String.t() | nil, result_set_size: non_neg_integer() | nil, rows_returned: non_neg_integer() | nil, system_peak_buffer_memory: term(), system_peak_temp_dir_size: term(), total_bytes_read: term(), total_bytes_written: term(), total_memory_allocated: term(), waiting_to_attach_latency: term(), wal_replay_entry_count: term(), write_to_wal_latency: term() }
Functions
@spec analyze(DBConnection.conn() | module(), iodata() | term(), [term()], keyword()) :: {:ok, t()} | {:error, Exception.t()}
Runs EXPLAIN (ANALYZE, FORMAT json) and returns a decoded DuckDB query profile.
Runs EXPLAIN (ANALYZE, FORMAT json) and returns a decoded DuckDB query profile, raising on errors.
@spec explain(DBConnection.conn() | module(), iodata() | term(), [term()], keyword()) :: {:ok, t()} | {:error, Exception.t()}
Runs EXPLAIN (FORMAT json) and returns a decoded DuckDB plan profile.
Runs EXPLAIN (FORMAT json) and returns a decoded DuckDB plan profile, raising on errors.
@spec flatten(t()) :: [operator_row()]
Converts DuckDB's profile tree into profiler-style operator rows.
Formats a compact text report for humans.
@spec slowest(t(), pos_integer()) :: [operator_row()]
Returns the slowest operators by operator_timing.