Skip to main content

Database Model

This document describes where and in what format the Platform stores data. Refer to this when determining backup scopes, performing direct queries, or adjusting retention periods.

Multiple Storage Types

The Platform uses polyglot persistence, dividing storage based on the nature of the data. If you do not know where specific data is located, your backup will be incomplete.

StorageContentsScale
PostgreSQLMaster data · Configuration · Transactionspp schema 169 tables + field app pf schema
Aster TSDB (pp)Time series · Events · Aggregations · KPI125 tables
Iceberg (spark.plantpulse)Long-term retention · Analytics1 table

PostgreSQL — Master and Configuration​

Relational data is stored here. Schema changes are managed by Flyway, and history is recorded in flyway_schema_history_v2.

Table names mostly consist of 159 entries with mm_ prefixes (master/meta). The full list by group is available below.

GroupRepresentative Tables
Organization·Assetmm_asset_tree · mm_enterprise · mm_site · mm_area · mm_line · mm_equipment · mm_asset_class
Collection Definitionmm_opc · mm_tag · mm_point · mm_edge
Alarmmm_alarm · mm_alarm_config · mm_alarm_delivery · mm_alarm_suppressed · mm_alarm_shelve · mm_alarm_out_of_service
Productionmm_order · mm_order_oee · mm_product · mm_shift · mm_calendar
Maintenance·Failuremm_maintenance_order · mm_maintenance_plan · mm_failure_record
People·Customermm_employee · mm_customer
Securitymm_security · mm_token · user_login · user_login_session

Relationship — Asset and Collection​

mm_asset_tree A single table contains all five layers: Enterprise(E) → Site(S) → Area(A) → Line(L) → Equipment(M). Columns shared across all layers, such as name, description, equipment classification, operation status, and external number, exist only in the tree — there is no site_name in mm_site, and no enterprise_name in mm_enterprise. Layer-specific unique columns are stored in 1:1 extension tables (mm_enterprise · mm_site · mm_area · mm_line · mm_equipment) and are deleted together when the corresponding tree row is removed.

RuleEnforcement
Parent must be the immediate upper layer; Area and below must belong to the same siteForeign keys fk_mm_asset_tree_parent · fk_mm_asset_tree_parent_site
Only Enterprise can be a root; Enterprise has no site_id; Site's site_id is itselfCHECK constraint
Layer-specific ID format — official prefix or legacy ASSET_CHECK chk_asset_id
Columns accepting only equipment (work orders, maintenance, calendars, etc.)Foreign keys referencing mm_equipment

Location paths are provided by view mv_path — for each node: asset_type · depth(Enterprise 0 ~ Equipment 4) · enterprise_id · site_id · area_id · line_id · equipment_id · id_path · name_path.

Relationship — Alarm​

Relationship — Production and User​

Foreign Keys Ensure Integrity

The above relationships are mostly declared as foreign keys. Therefore, attempting to DELETE a referenced row directly will either be rejected or deleted together depending on the table (ON DELETE CASCADE). Use the UI or API for deletions.

Full Tables (169)​

GroupTables
Organization·Asset (29)mm_area · mm_area_function · mm_asset_class · mm_asset_class_iso_class · mm_asset_connection_status · mm_asset_document · mm_asset_health_status · mm_asset_layout · mm_asset_plan_generation · mm_asset_plan_segment · mm_asset_qr_access_audit · mm_asset_qr_token · mm_asset_relation · mm_asset_standard_profile · mm_asset_status · mm_asset_tree · mm_asset_type · mm_canvas · mm_enterprise · mm_equipment · mm_equipment_criticality · mm_image · mm_line · mm_line_kind · mm_operational_status · mm_site · mm_stats_site · mm_stats_system · mm_status
Collection Definition (11)mm_edge · mm_edge_status_snapshot · mm_opc · mm_opc_connection_status · mm_opc_latency_status · mm_opc_protocol · mm_opc_source_type · mm_point · mm_tag · mm_tag_java_type · mm_tag_type
Alarm (16)mm_alarm · mm_alarm_cause · mm_alarm_config · mm_alarm_config_recipient · mm_alarm_config_revision · mm_alarm_delay · mm_alarm_delivery · mm_alarm_label_revision · mm_alarm_notification · mm_alarm_out_of_service · mm_alarm_resolution_guide · mm_alarm_resolution_guide_cause · mm_alarm_shelve · mm_alarm_signal_gap · mm_alarm_suppressed · mm_tag_alarm_recipient
Equipment Command·Statement (13)mm_asset_command · mm_asset_command_revision · mm_asset_statement · mm_asset_statement_deployment · mm_asset_statement_plugin · mm_asset_statement_revision · mm_command_area · mm_command_execution · mm_command_execution_event · mm_command_switch · mm_command_switch_audit · mm_event · mm_event_attributes
Production (35)mm_calendar · mm_calendar_revision · mm_calendar_type · mm_defect_cause · mm_defect_record · mm_defect_record_revision · mm_holiday · mm_order · mm_order_ems · mm_order_flow · mm_order_note · mm_order_oee · mm_order_pause · mm_order_performance · mm_order_progress · mm_order_quantity_correction · mm_order_quantity_correction_revision · mm_order_ram · mm_order_revision · mm_process_segment · mm_process_segment_asset · mm_product · mm_product_route · mm_product_standard_profile · mm_production_target · mm_shift · mm_shift_override · mm_shift_pattern · mm_shift_pattern_asset · mm_shift_pattern_slot · mm_shift_schedule_revision · mm_shift_slot_break · mm_stop_cause · mm_stop_reason · mm_stop_reason_revision
Maintenance·Failure (25)mm_failure_record · mm_failure_record_change · mm_failure_record_label · mm_failure_record_link · mm_fault_cause · mm_fault_cause_alarm_cause · mm_fault_code_map · mm_fault_code_map_history · mm_iso_detection_method · mm_iso_equipment_category · mm_iso_equipment_class · mm_iso_failure_cause · mm_iso_failure_mechanism · mm_iso_failure_mode · mm_iso_failure_mode_class · mm_iso_maintainable_item · mm_iso_maintainable_item_class · mm_iso_maintenance_activity · mm_maintenance_attachment · mm_maintenance_code_map · mm_maintenance_code_map_history · mm_maintenance_order · mm_maintenance_order_revision · mm_maintenance_plan · mm_maintenance_plan_revision
People·Customer (10)mm_app_account · mm_app_account_audit · mm_app_account_revision · mm_app_account_scope · mm_customer · mm_employee · mm_employee_audit · mm_employee_emergency_contact · mm_employee_photo · mm_employee_qualification
Flow (5)mm_flow · mm_flow_health_status · mm_flow_link · mm_flow_node · mm_flow_snapshot
Security (3)mm_security · mm_security_asset_scope · mm_token
Others (22)mm_blob · mm_config · mm_diagnostic_code · mm_diagnostic_state · mm_metadata · mm_query_history · mm_reference_external_key · mm_reference_revision · mm_reference_text · mm_report · mm_schedule_fire_log · mm_schedule_watermark · dual · edge_active_flows · flow_snapshots · flyway_schema_history_v2 · metadata · node_component · user_login · user_login_session · version · version_history

Aster TSDB — Time Series and Events​

The keyspace is pp. The 125 tables are divided into two categories.

PrefixCountMeaning
tm_117Time series measurement, aggregation, statistics, KPI
ts_8Internal structure of the general-purpose time series engine

tm_ is further divided by target — Tags 32, KPI 26, Assets 17, System 6, Monitor 6, Options 5, OPC 5, Site 3, blob 3, etc.

Core Table — tm_tag_point​

This is where raw collection values are stored. Other tag tables are generally derived from this.

PRIMARY KEY (tag_id, timestamp)
WITH CLUSTERING ORDER BY (timestamp DESC)
PropertyValue
Partition Keytag_id — One tag per partition
Clusteringtimestamp Descending — Default is reading from newest first
Default TTL315360000 seconds = 3650 days (10 years) — Official value is in storage.tag.point.ttl (Retention Period Settings)
CompactionUnifiedCompactionStrategy (Cassandra 5.0+ feature)
IndexSAI(Storage Attached Index) on asset_id · opc_id
Why use static columns?

site_id · asset_id · line_id · area_id · opc_id · tag_name · type are static. Since the value is the same within a single tag (= one partition), it is stored only once per partition. This significantly reduces capacity as it avoids repeated storage for every data point.

Derived Tables — Pre-computed​

Since aggregation at query time is expensive in Aster TSDB, values are pre-calculated during writes. This results in a high number of tables.

CategoryExamples
Aggregationtm_tag_point_aggregation_{1,5,10,30}_minutes · _1_hours
Samplingtm_tag_point_sampling_{10,30}_seconds · _{1,5,10,30}_minutes · _1_hours
Counttm_tag_point_count · _by_date · _by_opc · _by_site
Quality·Validationtm_tag_point_validation · _by_timestamp · _validation_count
AI Analysistm_tag_point_anomalies · _forecasts
Snapshot·Retentiontm_tag_point_snapshot · tm_tag_point_archive

Alarms follow the same method — tm_tag_alarm and _count · _count_by_date · _count_by_opc · _count_by_site · _duration · _on.

Do not delete aggregation tables directly

They are not reconstructed from raw data. If deleted, screens and reports for that period will be blank, and recovery is only possible via backup.

KPI Tables — OEE · RAM · EMS​

Equipment KPIs (OEE · RAM · EMS) are stored in 26 tables starting with tm_kpi_ — categorized by domain as tm_kpi_oee_* · tm_kpi_ram_* · tm_kpi_ems_*. A calculation job writes values for each piece of equipment approximately every 10 seconds.

Legacy tm_asset_oee* · tm_asset_ram* · tm_asset_ems* tables no longer exist

KPIs are now written only to new tables. Queries and reports using old names must be updated to match the new tables and partition keys. Since keys have changed, using old conditions will likely result in empty results rather than errors, and these empty results are indistinguishable from 「No Data」.

Tables are divided into four categories based on their purpose.

CategoryNamePrimary KeyMeaning of one row
Current Valuetm_kpi_*_current(asset_id)Current value of equipment — one row per equipment, overwritten upon each calculation
Per Ordertm_kpi_oee_order · tm_kpi_ems_order(order_id)Value for a single work order — one row per order, remains after order completion
Historytm_kpi_*_history etc.((asset_id, day), timestamp)Value of one calculation (tick) — partition by UTC date, newest first
Rolluptm_kpi_*_rollup((scope, scope_id, day), timestamp)Values aggregated by line, area, site, or enterprise
  • Buckets are UTC dates. day is integer yyyymmdd, and month is integer yyyymm, representing the date interpreted as UTC for timestamp of the row — not the local midnight of the site. Therefore, one local day spans two UTC buckets (rows from 00:00 to 08:59 KST are in the previous day's UTC bucket).
  • Infrequent data uses monthly buckets — equipment status (tm_kpi_oee_status), failure (tm_kpi_ram_failure · _failure_rollup), and fuel (tm_kpi_ems_fuel) are partitioned by month.
  • Rollup scope is one of LINE · AREA · SITE · ENTERPRISE, and scope_id is the ID of that line, area, or site. Enterprise level is scope_id = 'ALL'.
  • Cause counters tm_kpi_oee_defect_cause · _stop_cause · _fault_cause are daily accumulations by defect, stop, or failure cause. The primary key is ((asset_id, month), date, cause_code).
  • History rows are order accumulations. One row of *_history is the total value for the order up to that tick (uptime, production count, energy, etc.). Do not sum the rows — for period values, read the last row per order or the *_order row.
  • Duration of equipment status is not stored. tm_kpi_oee_status only stores the time the status changed, and a status continues until the time in the next row. Do not cut at month boundaries; read buckets consecutively.
Querying — Provide all partition keys

Include both asset_id and day (or month) in the condition. Do not use ALLOW FILTERING. When querying a period, expand the period into a list of UTC dates and read once per bucket.

SELECT timestamp, oee, availability, performance, quality
FROM pp.tm_kpi_oee_history
WHERE asset_id = 'EQUIPMENT_000001' AND day = 20260925
AND timestamp >= '2026-09-25 00:00:00+0000';

If values per equipment belonging to a site are needed, obtain the equipment list from PostgreSQL and read tm_kpi_*_current for each equipment. Site totals are in scope = 'SITE' of the rollup table.

The retention period is 5 years. The default TTL for tables with buckets (history, event, status, rollup, etc.) is 157680000 seconds (1825 days), and the official value is in storage.asset.kpi.ttl (or storage.asset.standard.ttl if unavailable) (Retention Period Settings). Current value (*_current), per order (*_order), and cause counters have no TTL. Since 14 history tables are copied daily to tw_kpi_* in Iceberg, they can be queried in Iceberg even after being deleted from Aster TSDB after 5 years.


Data Separation — Partition Key as the Query Axis​

Aster TSDB does not support joins. Separate tables are created based on the query method — which is why there are 125 tables. Storing the same data in multiple tables with different partition keys is a design choice, not duplication.

Partition Key FormatPurposeExample
(tag_id) + timestampTime-axis query for a single tagtm_tag_point
(asset_id, date, hour) + timestampDaily/hourly interval for one equipmenttm_asset_data
(asset_id, day) + timestampUTC daily KPI for one equipmenttm_kpi_oee_history
(scope, scope_id, day) + timestampUTC daily KPI for line, area, site, or enterprisetm_kpi_oee_rollup
(site_id, year, month, day)Site-unit aggregationtm_site_summary
(id) onlyCurrent value — no time axis, no expiration*_count, *_last_update, tm_kpi_*_current

Full Tables (125)​

Tag · Point (32)​

TablePrimary Key (Partition · Clustering)
tm_tag_alarmtag_id, alarm_seq
tm_tag_alarm_count``
tm_tag_alarm_count_by_datetag_id, year, month, day, hour, minute
tm_tag_alarm_count_by_opc(opc_id, tag_id), year, month, day, hour, minute
tm_tag_alarm_count_by_site(site_id, tag_id), year, month, day, hour, minute
tm_tag_alarm_durationalarm_config_id, alarm_seq
tm_tag_alarm_on``
tm_tag_pointtag_id, timestamp
tm_tag_point_aggregation_10_minutestag_id, timestamp
tm_tag_point_aggregation_1_hourstag_id, timestamp
tm_tag_point_aggregation_1_minutestag_id, timestamp
tm_tag_point_aggregation_30_minutestag_id, timestamp
tm_tag_point_aggregation_5_minutestag_id, timestamp
tm_tag_point_anomaliesjob_id, timestamp, tag_id
tm_tag_point_archive(site_id, year, month, day, hour), minute, second, tuuid
tm_tag_point_count``
tm_tag_point_count_by_datetag_id, year, month, day, hour, minute
tm_tag_point_count_by_opc``
tm_tag_point_count_by_site``
tm_tag_point_forecastsjob_id, timestamp, tag_id
tm_tag_point_map(year, month, day, hour, minute), timestamp
tm_tag_point_sampling_10_minutestag_id, timestamp
tm_tag_point_sampling_10_secondstag_id, timestamp
tm_tag_point_sampling_1_hourstag_id, timestamp
tm_tag_point_sampling_1_minutestag_id, timestamp
tm_tag_point_sampling_30_minutestag_id, timestamp
tm_tag_point_sampling_30_secondstag_id, timestamp
tm_tag_point_sampling_5_minutestag_id, timestamp
tm_tag_point_snapshot(site_id, snapshot_id, date), timestamp
tm_tag_point_validationtag_id, timestamp
tm_tag_point_validation_by_timestampyyyymmdd, timestamp, tag_id
tm_tag_point_validation_counttag_id, year, month, day, hour, minute

Asset (17)​

TablePrimary Key (Partition · Clustering)
tm_asset_aggregationasset_id, timestamp
tm_asset_alarmasset_id, alarm_seq
tm_asset_commandasset_id, timestamp
tm_asset_connection_statusasset_id, timestamp
tm_asset_contextasset_id, timestamp
tm_asset_data(asset_id, date, hour), timestamp
tm_asset_data_anomaliesjob_id, timestamp, asset_id, tag_id
tm_asset_data_based_dayasset_id, timestamp
tm_asset_data_based_hourasset_id, timestamp
tm_asset_data_based_minute(asset_id, date), timestamp
tm_asset_data_based_second(asset_id, date, hour), timestamp
tm_asset_data_based_timestamp(asset_id, date, hour), timestamp
tm_asset_data_forecastsjob_id, timestamp, asset_id, tag_id
tm_asset_eventasset_id, timestamp
tm_asset_health_statusasset_id, timestamp
tm_asset_statusasset_id, timestamp
tm_asset_timelineasset_id, timestamp, timeline_group, timeline_type

KPI — OEE · RAM · EMS (26)​

The «Day» in the bucket column is day (UTC yyyymmdd), and «Month» is month (UTC yyyymm). The month of the cause counter is obtained from date. See the KPI Tables section for reading instructions.

TablePrimary Key (Partition · Clustering)BucketContents
tm_kpi_oee_currentasset_id—Current OEE of equipment
tm_kpi_oee_orderorder_id—OEE of a single work order
tm_kpi_oee_history(asset_id, day), timestampDayOEE per calculation tick (order accumulation)
tm_kpi_oee_event(asset_id, day), timestampDayOEE input events
tm_kpi_oee_count(asset_id, day), timestampDayGood/Defect production count (lot, serial)
tm_kpi_oee_rolling(asset_id, day), timestampDayOEE for the last N minutes
tm_kpi_oee_rollup(scope, scope_id, day), timestampDayLine, Area, Site, Enterprise OEE
tm_kpi_oee_status(asset_id, month), timestampMonthEquipment status change
tm_kpi_oee_status_currentasset_id—Previous status of equipment
tm_kpi_oee_defect_cause(asset_id, month), date, cause_codeMonthDaily accumulation of defect causes (counter)
tm_kpi_oee_stop_cause(asset_id, month), date, cause_codeMonthDaily accumulation of stop causes (counter)
tm_kpi_oee_fault_cause(asset_id, month), date, cause_codeMonthDaily accumulation of failure causes (counter)
tm_kpi_ram_currentasset_id—Current RAM of equipment
tm_kpi_ram_history(asset_id, day), timestampDayRAM per calculation tick (order accumulation)
tm_kpi_ram_failure(asset_id, month), timestampMonthFailure start/end events
tm_kpi_ram_failure_rollup(scope, scope_id, month), timestamp, asset_idMonthLine, Area, Site failure events
tm_kpi_ram_rolling(asset_id, day), timestampDayRAM for the last N minutes
tm_kpi_ram_rollup(scope, scope_id, day), timestampDayLine, Area, Site, Enterprise RAM
tm_kpi_ems_currentasset_id—Current EMS of equipment
tm_kpi_ems_orderorder_id—EMS of a single work order
tm_kpi_ems_history(asset_id, day), timestampDayEMS per calculation tick (order accumulation)
tm_kpi_ems_power(asset_id, day), timestampDayPower measurement events (kW, kWh)
tm_kpi_ems_power_rollup(scope, scope_id, day), timestamp, asset_idDayLine, Area, Site power events
tm_kpi_ems_fuel(asset_id, month), timestampMonthFuel measurement events (Scope 1)
tm_kpi_ems_rolling(asset_id, day), timestampDayEMS for the last N minutes
tm_kpi_ems_rollup(scope, scope_id, day), timestampDayLine, Area, Site, Enterprise EMS

Collection · Site (8)​

TablePrimary Key (Partition · Clustering)
tm_opc_connection_latency_historyopc_id, timestamp
tm_opc_connection_status_historyopc_id, timestamp
tm_opc_point_count``
tm_opc_point_count_by_dateopc_id, year, month, day, hour, minute
tm_opc_point_last_update``
tm_site_statussite_id, timestamp
tm_site_summarysite_id, year, month, day, hour, minute
tm_site_summary_total``

Monitoring (13)​

TablePrimary Key (Partition · Clustering)
tm_monitor_cep_metricstype, timestamp
tm_monitor_cluster_metricstype, ip, timestamp
tm_monitor_cluster_statustype, ip, timestamp
tm_monitor_nodestype, ip
tm_monitor_platform_healthtype, ip, timestamp
tm_monitor_platform_statustype, ip, timestamp
tm_system_health_statusapp_name, timestamp
tm_system_logapp_name, timestamp, seq
tm_system_log_count(app_name, level), year, month, day, hour, minute
tm_system_log_hourlyapp_name, bucket_start, instance_id, level
tm_system_propertiesproperty, timestamp
tm_system_start_date``
tm_system_trendyear, month, day, hour

Batch · Audit (4)​

TablePrimary Key (Partition · Clustering)
tm_batch_audityyyymmdd, timestamp, id
tm_batch_job_runyyyymmdd, timestamp, id
tm_warehouse_audityyyymmdd, timestamp, id
tm_warehouse_storage_usage_dailyyear_bucket, day, table_name

Time Series Engine (TSE Only) (8)​

TablePrimary Key (Partition · Clustering)
ts_data_pointskey, column1
ts_row_key_indexkey, column1
ts_row_key_time_indexmetric, table_name, row_time
ts_row_keys(metric, table_name, row_time), data_type, tags
ts_service_index(service, service_key), key
ts_specspec_type, name
ts_string_indexkey, column1
ts_tag_indexed_row_keys(metric, table_name, row_time, single_tag_pair), data_type, tag_collection_hash, tags

Others (17)​

TablePrimary Key (Partition · Clustering)
tm_blobblob_id, timestamp
tm_blob_count_and_size``
tm_blob_object``
tm_data_gateway_count``
tm_data_gateway_loglang, timestamp
tm_database_sizekeyspace_name, date
tm_diagnosticyear, timestamp
tm_diagnostic_countyear, level
tm_domain_change_history(domain_type, object_id), timestamp
tm_edge_status``
tm_option_eql_listener_result``
tm_option_eql_statement``
tm_option_eql_statement_historystmt_name, timestamp
tm_option_job_trigger_historyjob_name, context_fire_time
tm_option_listener_push_cacheurl, timestamp
tm_pipeline_exception_historybucket, timestamp, type, object_id
tm_trigger_resulttrigger_id, timestamp

Iceberg — Long-term Retention​

Data from archive tables (tm_tag_point_archive, default 365 days) is accumulated in object storage for analysis. Data does not move directly from raw tables but goes through an archive process.

ItemValue
Catalogspark.plantpulse
Tabletw_tag_point — Tag time series. There are 9 types starting with tw_asset_* · tw_blob etc. tw_. KPIs have 14 separate types in tw_kpi_*
Partitionsite_id → year → month → day
FormatIceberg v2 (supports row-level delete)
CompressionZstandard
ExecutionSpark SQL

KPI Archive — tw_kpi_*​

KPIs are moved directly from tm_kpi_* without passing through archive tables. Since the previous day's data is copied every dawn, recent data exists in both Aster TSDB and Iceberg, while data older than 5 years (TTL) remains only in Iceberg. Data in Iceberg is not deleted. Partitions are year → month → day (for monthly bucket tables: year → month).

Aster TSDBIceberg
tm_kpi_oee_history · _event · _count · _status · _rolluptw_kpi_oee_history · _event · _count · _status · _rollup
tm_kpi_ram_history · _failure · _rollup · _failure_rolluptw_kpi_ram_history · _failure · _rollup · _failure_rollup
tm_kpi_ems_history · _power · _fuel · _rollup · _power_rolluptw_kpi_ems_history · _power · _fuel · _rollup · _power_rollup

Current value (*_current · oee_status_current), per order (*_order), last N minutes (*_rolling), and cause counters (*_cause) are not moved — they are either not history or can be recalculated from history.

Searching for data beyond the retention period

It is no longer in Aster TSDB. Query the Iceberg side → Analytics Layer. Retention periods per table are in Data Retention Period (TTL) Settings.


Common Backup Omissions​

The three storage types must each be backed up. A common mistake is to only back up PostgreSQL, which would result in the total loss of time series data.

StorageRisk of Omission
PostgreSQLLoss of equipment/tag definitions, users, and dashboards
Aster TSDBLoss of time series data within the retention period
Iceberg / Object StorageLoss of long-term history

For procedures, refer to Backup and Recovery.