View Source ActiveMemory.Candidates (ActiveMemory v0.8.2)
Finds database tables whose workload — read constantly, written rarely — makes
them candidates for an ActiveMemory.Table.
This is the engine behind mix active_memory.candidates, which runs it against
the host application's own Ecto repo. The analysis itself is pure, so it can also
be fed rows gathered any other way.
the-heuristic
The heuristic
A table is a candidate when its read/write ratio is high and it is small enough to hold in memory. Reads and writes come from the database's own statistics:
- PostgreSQL:
pg_stat_user_tables— reads are scans (seq_scan + idx_scan, each query touching the table counts once), writes are rows changed (n_tup_ins + n_tup_upd + n_tup_del). - MySQL/MariaDB:
performance_schema.table_io_waits_summary_by_table— reads are row fetch operations (COUNT_FETCH), writes are row change operations (COUNT_INSERT + COUNT_UPDATE + COUNT_DELETE).
The two databases count reads differently (queries vs rows), so ratios are not comparable across databases — only between tables of the same one, which is what matters for finding candidates.
Statistics are cumulative: since the last statistics reset on PostgreSQL, and since server start on MySQL. Run against a database that has seen production-like traffic, or the ratios describe nothing.
Link to this section Summary
Functions
Classify raw statistics rows ([table, rows, bytes, reads, writes]).
Render analyzed results as a text report.
The statistics query for an Ecto adapter.
Link to this section Types
@type t() :: %ActiveMemory.Candidates{ bytes: non_neg_integer(), ratio: float() | :infinity, reads: non_neg_integer(), rows: non_neg_integer(), table: String.t(), verdict: :strong | :candidate | :too_large | :write_heavy | :infrastructure | :no_traffic, writes: non_neg_integer() }
Link to this section Functions
Classify raw statistics rows ([table, rows, bytes, reads, writes]).
Options:
:min_ratio— reads per write to call a table a candidate (default 10; ten times that is a strong candidate):max_rows— above this a table is:too_largefor the in-memory sweet spot regardless of its ratio (default 50000):min_reads— below this many total operations a table's ratio carries no signal (one stray read of an untouched table is an infinite ratio), so it is reported as having too little traffic to judge (default 100)
Results are sorted candidates first, then by reads.
Render analyzed results as a text report.
The statistics query for an Ecto adapter.
Returns {:ok, sql} whose result rows are
[table, row_estimate, total_bytes, reads, writes], or {:error, message} for
an adapter without table-level read/write statistics.