Skip to content

Graphic preview

100%
Page type: how-to

Count schema objects

Run ptah schema stats to emit one OpenMetrics gauge per object kind in a live database and feed it to a metrics collector.

ptah schema stats reads a live database and writes one gauge per object kind in the OpenMetrics text format. Use it to record how much a schema holds over time — tables, columns, indexes, views, policies, grants — on a dashboard beside the rest of your infrastructure metrics.

Ptah emits metrics text and exits; it does not ship a dashboard or metrics server. Download the real OpenMetrics output generated from the committed SQLite fixture, then feed that text to the collector and visualization system you already operate.

Prerequisites: an installed ptah binary (Install Ptah) and the URL of the database to read. The command connects and reads nothing else: it takes no --root-dir and no --schema-file, so it describes a database rather than a desired schema. See Database URLs and dev databases for the URL forms --db-url accepts.

The examples run against one SQLite database, so they need no server. Save this as schema.sql:

CREATE TABLE customers (
id INTEGER NOT NULL PRIMARY KEY,
email TEXT NOT NULL,
country TEXT NOT NULL
);
CREATE TABLE orders (
id INTEGER NOT NULL PRIMARY KEY,
customer_id INTEGER NOT NULL REFERENCES customers (id),
total_cents INTEGER NOT NULL DEFAULT 0
);
CREATE INDEX idx_customers_country ON customers (country);
CREATE VIEW order_totals AS
SELECT customer_id AS buyer, total_cents AS cents FROM orders;
CREATE VIEW customer_orders AS
SELECT c.email, o.total_cents FROM customers c JOIN orders o ON o.customer_id = c.id;

Create the database from it:

Terminal window
ptah schema apply --schema-file schema.sql --db-url sqlite://shop.db --auto-approve

Expected output includes:

Auto-approval enabled; applying schema changes.
Schema apply completed successfully.

Substitute your own database URL throughout.

Terminal window
ptah schema stats --db-url sqlite://shop.db

Expected output includes:

# HELP ptah_schema_schemas Schemas declared or read.
# TYPE ptah_schema_schemas gauge
ptah_schema_schemas{dialect="sqlite"} 0
# HELP ptah_schema_tables Tables.
# TYPE ptah_schema_tables gauge
ptah_schema_tables{dialect="sqlite"} 4
# HELP ptah_schema_columns Columns across tables, excluding external tables.
# TYPE ptah_schema_columns gauge
ptah_schema_columns{dialect="sqlite"} 11
# HELP ptah_schema_indexes Indexes.
# TYPE ptah_schema_indexes gauge
ptah_schema_indexes{dialect="sqlite"} 2
# HELP ptah_schema_constraints Table-level constraints.
# TYPE ptah_schema_constraints gauge
ptah_schema_constraints{dialect="sqlite"} 0
# HELP ptah_schema_enums Enum types.
# TYPE ptah_schema_enums gauge
ptah_schema_enums{dialect="sqlite"} 0
# HELP ptah_schema_extensions Extensions.
# TYPE ptah_schema_extensions gauge
ptah_schema_extensions{dialect="sqlite"} 0
# HELP ptah_schema_functions Functions and procedures.
# TYPE ptah_schema_functions gauge
ptah_schema_functions{dialect="sqlite"} 0
# HELP ptah_schema_sequences Standalone sequences.
# TYPE ptah_schema_sequences gauge
ptah_schema_sequences{dialect="sqlite"} 0
# HELP ptah_schema_domains Domain types.
# TYPE ptah_schema_domains gauge
ptah_schema_domains{dialect="sqlite"} 0
# HELP ptah_schema_composite_types Composite types.
# TYPE ptah_schema_composite_types gauge
ptah_schema_composite_types{dialect="sqlite"} 0
# HELP ptah_schema_range_types Range types.
# TYPE ptah_schema_range_types gauge
ptah_schema_range_types{dialect="sqlite"} 0
# HELP ptah_schema_views Views.
# TYPE ptah_schema_views gauge
ptah_schema_views{dialect="sqlite"} 0
# HELP ptah_schema_materialized_views Materialized views.
# TYPE ptah_schema_materialized_views gauge
ptah_schema_materialized_views{dialect="sqlite"} 0
# HELP ptah_schema_triggers Triggers.
# TYPE ptah_schema_triggers gauge
ptah_schema_triggers{dialect="sqlite"} 0
# HELP ptah_schema_rls_policies Row-level security policies.
# TYPE ptah_schema_rls_policies gauge
ptah_schema_rls_policies{dialect="sqlite"} 0
# HELP ptah_schema_roles Roles.
# TYPE ptah_schema_roles gauge
ptah_schema_roles{dialect="sqlite"} 0
# HELP ptah_schema_grants Privilege grants.
# TYPE ptah_schema_grants gauge
ptah_schema_grants{dialect="sqlite"} 0
# HELP ptah_schema_clickhouse_refreshable_materialized_views Materialized views with a captured ClickHouse refresh schedule.
# TYPE ptah_schema_clickhouse_refreshable_materialized_views gauge
ptah_schema_clickhouse_refreshable_materialized_views{dialect="sqlite"} 0
# HELP ptah_schema_clickhouse_row_policies ClickHouse row policies captured as owned feature objects.
# TYPE ptah_schema_clickhouse_row_policies gauge
ptah_schema_clickhouse_row_policies{dialect="sqlite"} 0
# HELP ptah_schema_clickhouse_index_settings Indexes with captured ClickHouse data-skipping settings.
# TYPE ptah_schema_clickhouse_index_settings gauge
ptah_schema_clickhouse_index_settings{dialect="sqlite"} 0
# HELP ptah_schema_clickhouse_table_settings Tables with captured ClickHouse storage settings.
# TYPE ptah_schema_clickhouse_table_settings gauge
ptah_schema_clickhouse_table_settings{dialect="sqlite"} 0
# HELP ptah_schema_cockroachdb_row_ttl_tables Tables with a captured CockroachDB row-level TTL.
# TYPE ptah_schema_cockroachdb_row_ttl_tables gauge
ptah_schema_cockroachdb_row_ttl_tables{dialect="sqlite"} 0
# HELP ptah_schema_security_policies SQL Server security policies.
# TYPE ptah_schema_security_policies gauge
ptah_schema_security_policies{dialect="sqlite"} 0
# HELP ptah_schema_security_predicates Predicates SQL Server security policies bind to tables.
# TYPE ptah_schema_security_predicates gauge
ptah_schema_security_predicates{dialect="sqlite"} 0
# HELP ptah_schema_mysql_column_character_sets Columns with a captured MySQL-family character set.
# TYPE ptah_schema_mysql_column_character_sets gauge
ptah_schema_mysql_column_character_sets{dialect="sqlite"} 0
# HELP ptah_schema_mysql_column_on_update_clauses Columns with a captured MySQL-family ON UPDATE clause.
# TYPE ptah_schema_mysql_column_on_update_clauses gauge
ptah_schema_mysql_column_on_update_clauses{dialect="sqlite"} 0
# HELP ptah_schema_mysql_index_options MySQL and MariaDB index options an index states.
# TYPE ptah_schema_mysql_index_options gauge
ptah_schema_mysql_index_options{dialect="sqlite"} 0
# HELP ptah_schema_mysql_index_block_sizes Indexes with a MySQL-family KEY_BLOCK_SIZE hint.
# TYPE ptah_schema_mysql_index_block_sizes gauge
ptah_schema_mysql_index_block_sizes{dialect="sqlite"} 0
# HELP ptah_schema_spanner_row_deletion_policy_tables Tables with a captured Spanner row deletion policy.
# TYPE ptah_schema_spanner_row_deletion_policy_tables gauge
ptah_schema_spanner_row_deletion_policy_tables{dialect="sqlite"} 0
# HELP ptah_schema_continuous_aggregates TimescaleDB continuous aggregates.
# TYPE ptah_schema_continuous_aggregates gauge
ptah_schema_continuous_aggregates{dialect="sqlite"} 0
# HELP ptah_schema_hypertables Tables partitioned as TimescaleDB hypertables.
# TYPE ptah_schema_hypertables gauge
ptah_schema_hypertables{dialect="sqlite"} 0
# HELP ptah_schema_async_replications Async replications.
# TYPE ptah_schema_async_replications gauge
ptah_schema_async_replications{dialect="sqlite"} 0
# HELP ptah_schema_changefeeds Table changefeeds.
# TYPE ptah_schema_changefeeds gauge
ptah_schema_changefeeds{dialect="sqlite"} 0
# HELP ptah_schema_changefeed_consumers Consumers of table changefeeds.
# TYPE ptah_schema_changefeed_consumers gauge
ptah_schema_changefeed_consumers{dialect="sqlite"} 0
# HELP ptah_schema_ydb_column_families YDB column families a table states, without a default family that states nothing.
# TYPE ptah_schema_ydb_column_families gauge
ptah_schema_ydb_column_families{dialect="sqlite"} 0
# HELP ptah_schema_coordination_nodes Standalone coordination nodes.
# TYPE ptah_schema_coordination_nodes gauge
ptah_schema_coordination_nodes{dialect="sqlite"} 0
# HELP ptah_schema_external_data_sources External data sources.
# TYPE ptah_schema_external_data_sources gauge
ptah_schema_external_data_sources{dialect="sqlite"} 0
# HELP ptah_schema_external_tables External tables.
# TYPE ptah_schema_external_tables gauge
ptah_schema_external_tables{dialect="sqlite"} 0
# HELP ptah_schema_external_columns Columns across external tables.
# TYPE ptah_schema_external_columns gauge
ptah_schema_external_columns{dialect="sqlite"} 0
# HELP ptah_schema_resource_pools Resource pools.
# TYPE ptah_schema_resource_pools gauge
ptah_schema_resource_pools{dialect="sqlite"} 0
# HELP ptah_schema_resource_pool_classifiers Resource pool classifiers.
# TYPE ptah_schema_resource_pool_classifiers gauge
ptah_schema_resource_pool_classifiers{dialect="sqlite"} 0
# HELP ptah_schema_secrets Secret objects, without their values.
# TYPE ptah_schema_secrets gauge
ptah_schema_secrets{dialect="sqlite"} 0
# HELP ptah_schema_streaming_queries Standalone streaming queries.
# TYPE ptah_schema_streaming_queries gauge
ptah_schema_streaming_queries{dialect="sqlite"} 0
# HELP ptah_schema_topics Standalone topics.
# TYPE ptah_schema_topics gauge
ptah_schema_topics{dialect="sqlite"} 0
# HELP ptah_schema_topic_consumers Consumers of standalone topics.
# TYPE ptah_schema_topic_consumers gauge
ptah_schema_topic_consumers{dialect="sqlite"} 0
# HELP ptah_schema_transfers Transfers.
# TYPE ptah_schema_transfers gauge
ptah_schema_transfers{dialect="sqlite"} 0
# HELP ptah_schema_ydb_ttl_tables Tables with a captured YDB TTL.
# TYPE ptah_schema_ydb_ttl_tables gauge
ptah_schema_ydb_ttl_tables{dialect="sqlite"} 0
# EOF

The HELP lines describe the metric families. The selected build determines their names and order, independently of the target. Every registered family appears on every run, at zero where the captured schema holds no values. Zero does not establish that inspection covered that family. The body ends with a literal # EOF line, which lets a collector identify a complete scrape.

An unavailable feature reporter or an invalid count fails the command before it writes the scrape. An embedding application can select additional model reporters through the public Go API.

On YDB, standalone topics and their consumers are separate from table changefeeds and their consumers. Disabled changefeeds still contribute to the counts. External tables and their columns also have separate families; the ordinary table and column counters exclude them. Secrets contribute only an object count, never their names or values.

The counts describe the schema, not the contents. Row counts, table sizes, and index bloat are properties of the data, and the database’s own statistics views report those.

--schemas takes a comma-separated list. It selects which schemas to count on the PostgreSQL family, and adds a schemas label to every family whatever the engine:

Terminal window
ptah schema stats --db-url sqlite://shop.db --schemas main

Expected output includes:

ptah_schema_tables{dialect="sqlite",schemas="main"} 2

The label carries the flag’s value as one string. --schemas app,audit produces schemas="app,audit" on every family rather than one series per schema, so a pipeline that wants a series per schema runs the command once per schema.

The command writes one scrape and exits. There is no listener and no /metrics path, so the usual shape is a scheduled run that writes a file a collector already watches, such as the node_exporter textfile directory:

Terminal window
ptah schema stats --db-url sqlite://shop.db > schema-shape.prom
grep '^ptah_schema_tables' schema-shape.prom

Expected output includes:

ptah_schema_tables{dialect="sqlite"} 2

A successful read exits 0. A usage error or a connection failure exits 2 with one line on stderr, for example error: --db-url is required. See Exit codes for the contract.

  • A zero counts what Ptah’s reader returned, not what the server holds. Where Ptah reads no triggers for a dialect, ptah_schema_triggers is 0 and nothing separates that from a database with no triggers.
  • ptah_schema_schemas reports 0 on SQLite, which models no schema catalog.
  • --db-url or PTAH_DB_URL is the only source of the target. A ptah.yaml carrying a url: does not satisfy it, and the run exits 2 with error: --db-url is required.

Run ptah schema stats --help for the flag set with its environment variables. Schema object counts places the verb in the native tree, and Exit codes carries its row.