Conceptual, Logical and Physical Data Models

Data models are built at three levels of detail: conceptual, logical and physical. This page explains what each level shows and who it is for, then takes a single online-shop example through all three, ending in runnable SQL.


1. What the Three Levels Are

Three Levels of a Data Model Conceptual what the business means audience: stakeholders Logical structure, keys, rules audience: analysts, architects Physical how one DBMS stores it audience: engineers, DBAs Each level adds detail and removes ambiguity; each is tied less to the business and more to technology. Entities and relationships -> attributes, keys, normalisation -> types, indexes, partitions

Data modelling is usually done at three levels of detail, a framework that goes back to the ANSI/SPARC architecture of the 1970s:

2. Why Separate Them

Each level serves a different conversation. The conceptual model lets business stakeholders confirm that the system understands their world ("can an order belong to two customers?") without being distracted by data types. The logical model is where precision about meaning lives: what uniquely identifies a product, whether a customer can exist without an order, which attributes depend on which keys. The physical model is where performance and platform constraints enter.

Keeping them separate means a change of technology (say, moving from an on-premise database to a cloud warehouse) changes only the physical model, and a change in business rules is discussed at the level where it is cheapest to fix. Errors found at the conceptual level cost a conversation; the same error found after the physical schema is in production costs a migration.

3. How a Model Evolves Through the Levels

Worked Example: Conceptual and Logical Views of an Online Shop Conceptual Customer Order Product a customer places orders; an order contains products Logical Customer PK customer_id email (unique) Order PK order_id FK customer_id Product PK product_id name, price OrderLine PK order_id, line_no; FK x2 No attributes, no keys, many-to-many left as-is M:N resolved by an associative entity

Take a simple online shop. The conceptual step starts from interviews: customers place orders, orders contain products. Three entities and two relationships, with the order-to-product relationship being many-to-many (an order has many products; a product appears in many orders). That is enough to validate scope with the business.

The logical step adds precision:

  1. List attributes for each entity and assign each to the entity it describes (customer email belongs to Customer, not Order).
  2. Choose identifiers: a primary key for each entity, plus natural candidate keys such as a unique email.
  3. Resolve many-to-many relationships with an associative entity. Order and Product are linked by OrderLine, which carries attributes that belong to the pair: quantity and the price charged.
  4. State cardinality and optionality: each order has exactly one customer and one or more lines; a customer may have zero orders.
  5. Normalise so each fact is stored once. That is why the price on OrderLine is a separate fact from the product's current list price: it records what was charged.

The physical step then picks a target platform and makes concrete choices.

4. Worked Example: The Physical Model

-- Physical model for PostgreSQL, derived from the logical model above.
CREATE TABLE customer (
    customer_id   BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    email         VARCHAR(320) NOT NULL UNIQUE,
    full_name     VARCHAR(200) NOT NULL,
    created_at    TIMESTAMPTZ  NOT NULL DEFAULT now()
);

CREATE TABLE product (
    product_id    BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    name          VARCHAR(200)  NOT NULL,
    unit_price    NUMERIC(10,2) NOT NULL CHECK (unit_price >= 0)
);

CREATE TABLE customer_order (                -- "order" is a reserved word
    order_id      BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    customer_id   BIGINT NOT NULL REFERENCES customer(customer_id),
    order_date    DATE   NOT NULL,
    status        VARCHAR(20) NOT NULL DEFAULT 'placed'
);
CREATE INDEX ix_order_customer ON customer_order (customer_id, order_date);

CREATE TABLE order_line (
    order_id      BIGINT  NOT NULL REFERENCES customer_order(order_id) ON DELETE CASCADE,
    line_no       INT     NOT NULL,
    product_id    BIGINT  NOT NULL REFERENCES product(product_id),
    quantity      INT     NOT NULL CHECK (quantity > 0),
    unit_price    NUMERIC(10,2) NOT NULL,   -- price at time of sale, not current price
    PRIMARY KEY (order_id, line_no)
);

Notice the decisions that appear only at this level: order renamed to customer_order because it is a reserved word; surrogate identity keys; NUMERIC(10,2) for money rather than floating point; TIMESTAMPTZ for time zones; a composite index chosen because the application's most common query is "a customer's recent orders"; and a cascading delete policy. None of these change what the data means, which is exactly the point.

5. Same Logic, Different Physical Designs

One Logical Model, Different Physical Designs Logical: Order, OrderLine 3NF, keys, cardinalities PostgreSQL (OLTP) normalised tables, FK constraints, B-tree indexes on customer_id Cloud warehouse (OLAP) denormalised fact_order_line, partition / cluster by order_date

The same logical model can have several physical models. For the transactional application, normalised tables with enforced foreign keys protect integrity under concurrent updates. For analytics, the warehouse version might flatten order and order line into one wide fact table with denormalised customer and product attributes, partitioned or clustered by date, because analytical scans favour fewer joins and pruning by date. Both are faithful to the logical model; they optimise for different workloads.

Analytical platforms add one more twist. Many teams keep a normalised, source-aligned logical model for the integrated "core" layer, and a separate dimensional logical model (facts, dimensions, grain) for the marts that serve reporting. Both are logical models in the sense used here: product-independent statements of structure and meaning. Each then has its own physical design. Keeping the dimensional model explicit, including the declared grain of every fact table ("one row per order line"), prevents the most common analytics error, which is joining tables at different grains and silently double-counting. Tools such as dbt make the physical layer visible as code, but they do not replace the logical decisions; write those down in the model documentation, next to the SQL, so that a reviewer can check the implementation against the intent.

6. Comparison Table

AspectConceptualLogicalPhysical
PurposeAgree on scope and meaningDefine structure and rules preciselyImplement efficiently on a platform
ContainsEntities, relationshipsAttributes, keys, cardinality, normal formTables, types, indexes, partitions, constraints
Technology-specific?NoNoYes
Typical notationSimple ER or boxes and linesER with crow's foot, IDEF1XDDL, database diagrams
Main audienceBusiness stakeholdersAnalysts, data architectsEngineers, DBAs
Changes whenBusiness scope changesBusiness rules changePlatform or workload changes

7. Pitfalls

9. Further Reading