Skip to content
COHARYN
← InsightsUnknown systems

How to Understand an Undocumented Enterprise Database Safely

7 min read

Most enterprises run at least one database that nobody fully understands. The original authors have moved on, the documentation is a wiki page from three reorganisations ago, and the only reliable source of truth is the running system itself. When you are handed such a database and asked what it means, the instinct is to open a client and start querying. That instinct is also how outages happen. A production database that has kept a business alive for a decade deserves to be approached like a live archaeological site, not a scratch pad.

The safe way to understand an undocumented database is to work outward from the cheapest, least invasive evidence toward the more expensive kind, and to stop as soon as you have enough confidence for the decision in front of you. You almost never need to read every row. You need to read the right metadata, use the statistics the engine already maintains, and sample deliberately when a question genuinely requires it.

Start with the catalog, not the data

Every supported engine keeps a rich description of itself. PostgreSQL exposes pg_catalog and the information_schema views. Oracle has the ALL_ and DBA_ dictionary views. SQL Server has sys.tables, sys.columns, and the related system objects. MySQL exposes information_schema as well. These sources are free to read, they do not touch table data, and they answer a surprising fraction of the questions you actually have: what tables exist, what columns they hold, which types were chosen, what is nullable, what defaults were set, which constraints and indexes were declared, and which objects reference which through views and stored procedures.

Reading the catalog first also tells you where the meaning is likely to hide. A column typed as VARCHAR that stores a small set of repeating codes is almost certainly an enumeration the schema never declared. A table with no primary key is a warning sign about identity. A nullable foreign-key-shaped column with no declared constraint is a relationship waiting to be confirmed. None of this requires scanning a single row.

Use the statistics the engine already computed

Query planners depend on table and column statistics, and those statistics are a gift to anyone trying to understand data cheaply. Row-count estimates, distinct-value counts, null fractions, most-common-value lists, and histograms are maintained by the engine for its own purposes and can be read without a full scan. They let you estimate selectivity, spot columns that behave like keys because their distinct count approaches the row count, and identify columns that behave like categories because a handful of values dominate.

Treat these numbers as evidence with a known freshness, not as ground truth. Statistics can be stale, and on some engines they are sampled rather than exact. That is fine. The point of the statistics pass is to form hypotheses cheaply, then confirm only the ones that matter with a targeted, bounded query.

Sample within bounds, deliberately

When a question truly needs to look at data, sample rather than scan, and put a ceiling on the work. A bounded sample, taken with the engine’s own sampling mechanism or with a limited, indexed read, is usually enough to characterise a column’s value distribution, confirm a format, or check whether a supposed key ever repeats. Reserve full scans for the rare cases where a rare event matters and sampling could miss it, such as proving that a column is unique or that a relationship has zero orphans.

  • Prefer catalog and statistics reads before any data read.
  • Cap sample size and query cost so exploration can never dominate the workload.
  • Read from replicas or off-peak windows when touching large tables.
  • Escalate from sample to full scan only for claims that must be exact, like uniqueness or zero orphans.

Profile columns to recover lost meaning

Column profiling is where an undocumented schema starts to speak. For each column you care about, gather the practical shape of its values: cardinality relative to row count, null fraction, minimum and maximum, common patterns, and the set of distinct values when that set is small. A column with a dozen distinct string values across millions of rows is an undeclared enumeration, and its values often name the business states that the system actually cares about. A column whose values all match a fixed length and character class is likely an external identifier. A monotonically increasing integer with near-unique values is a surrogate key even when no constraint says so.

Profiling turns anonymous columns into candidates with roles. Those roles are hypotheses, and the next step is to test the relationships between them.

Infer entities and relationships from evidence

With per-column profiles in hand, you can reconstruct the entity model the schema forgot to declare. Group columns into candidate keys and candidate attributes. Look for value containment between a candidate key in one table and a candidate reference in another, then check the direction and the cardinality of that containment. A reference whose values are entirely contained in a parent key, with a many-to-one shape, is a relationship the database has been enforcing informally for years. Naming and type similarity can point you toward candidates, but they are weak evidence on their own and must be confirmed against the data.

The database is the most honest documentation you have. Everything else describes what someone intended; the data records what actually happened.

The discipline that keeps this safe is to treat every conclusion as evidence-backed and revisable. Record why you believe a column is a key, why you believe two tables are related, and what sample or statistic supports it. In controlled, synthetic validation of this approach, models rebuilt from catalog, statistics, and bounded profiling recovered the intended structure of deliberately undocumented schemas without full-table scans. The lesson generalises: understanding a legacy database is less about reading everything and more about reading the right things in the right order, then letting the evidence, not the folklore, define the model.

Start with a private pilot.

Connect Coharyn read-only to one unfamiliar system, or several. See what it discovers, with evidence, before you commit to anything.