Pagila Database Schema Diagram
Pagila is the PostgreSQL port of MySQL's Sakila DVD-rental sample database, designed to showcase Postgres features. Films describe titles with a full-text search column; inventory holds physical copies per store; rentals link inventory to customers and staff; payments record each rental's charge. Sixteen tables are mapped above. Two details worth knowing: the payment table is range-partitioned by month in production (the monthly partitions are omitted here for readability), and the film table carries a film_embedding vector column plus a tsvector fulltext column - the Postgres-specific additions that distinguish Pagila from Sakila.
Last updated: 2026-09-27
Tables in the Pagila schema
| Column | Type | Nullable | Key |
|---|---|---|---|
| customer | |||
| customer_id | integer | No | PK |
| store_id | integer | No | - |
| first_name | text | No | - |
| last_name | text | No | - |
| text | Yes | - | |
| address_id | integer | No | - |
| activebool | boolean | No | - |
| create_date | date | No | - |
| last_update | timestamp with time zone | Yes | - |
| active | integer | Yes | - |
| uuid | uuid | No | - |
| actor | |||
| actor_id | integer | No | PK |
| first_name | text | No | - |
| last_name | text | No | - |
| last_update | timestamp with time zone | No | - |
| category | |||
| category_id | integer | No | PK |
| name | text | No | - |
| last_update | timestamp with time zone | No | - |
| film | |||
| film_id | integer | No | PK |
| title | text | No | - |
| description | text | Yes | - |
| release_year | public.year | Yes | - |
| language_id | integer | No | - |
| original_language_id | integer | Yes | - |
| rental_duration | smallint | No | - |
| rental_rate | numeric(4,2) | No | - |
| length | smallint | Yes | - |
| replacement_cost | numeric(5,2) | No | - |
| rating | public.mpaa_rating | Yes | - |
| last_update | timestamp with time zone | No | - |
| special_features | text[] | Yes | - |
| fulltext | tsvector | No | - |
| length_hours | numeric(4,2) GENERATED ALWAYS AS (round(length / 60.0, 2)) VIRTUAL | Yes | - |
| film_actor | |||
| actor_id | integer | No | PK |
| film_id | integer | No | PK |
| last_update | timestamp with time zone | No | - |
| film_category | |||
| film_id | integer | No | PK |
| category_id | integer | No | PK |
| last_update | timestamp with time zone | No | - |
| film_embedding | |||
| film_id | integer | No | PK |
| embedding | public.vector(20) | No | - |
| last_update | timestamp with time zone | No | - |
| address | |||
| address_id | integer | No | PK |
| address | text | No | - |
| address2 | text | Yes | - |
| district | text | No | - |
| city_id | integer | No | - |
| postal_code | text | Yes | - |
| phone | text | No | - |
| last_update | timestamp with time zone | No | - |
| city | |||
| city_id | integer | No | PK |
| city | text | No | - |
| country_id | integer | No | - |
| last_update | timestamp with time zone | No | - |
| country | |||
| country_id | integer | No | PK |
| country | text | No | - |
| last_update | timestamp with time zone | No | - |
| inventory | |||
| inventory_id | integer | No | PK |
| film_id | integer | No | - |
| store_id | integer | No | - |
| last_update | timestamp with time zone | No | - |
| language | |||
| language_id | integer | No | PK |
| name | text | No | - |
| last_update | timestamp with time zone | No | - |
| payment | |||
| payment_id | integer | No | PK |
| customer_id | integer | No | - |
| staff_id | integer | No | - |
| rental_id | integer | No | - |
| amount | numeric(5,2) | No | - |
| payment_date | timestamp with time zone | No | PK |
| uuid | uuid | No | - |
| rental | |||
| rental_id | integer | No | PK |
| rental_date | timestamp with time zone | No | - |
| inventory_id | integer | No | - |
| customer_id | integer | No | - |
| return_date | timestamp with time zone | Yes | - |
| staff_id | integer | No | - |
| last_update | timestamp with time zone | No | - |
| uuid | uuid | No | - |
| staff | |||
| staff_id | integer | No | PK |
| first_name | text | No | - |
| last_name | text | No | - |
| address_id | integer | No | - |
| text | Yes | - | |
| store_id | integer | No | - |
| active | boolean | No | - |
| username | text | No | - |
| password | text | Yes | - |
| last_update | timestamp with time zone | No | - |
| picture | bytea | Yes | - |
| store | |||
| store_id | integer | No | PK |
| manager_staff_id | integer | No | - |
| address_id | integer | No | - |
| last_update | timestamp with time zone | No | - |
Frequently asked questions
What tables are in the Pagila database?
Pagila has 16 logical tables: actor, film, film_actor, film_category, film_embedding, category, language, inventory, store, staff, customer, address, city, country, rental, and payment - plus monthly payment partitions in production.
What is the difference between Pagila and Sakila?
Pagila is a port of MySQL's Sakila DVD-store sample to PostgreSQL with Postgres-native changes: boolean flags instead of char(1), real foreign keys, tsvector full-text search on film, a film_embedding vector column, and a range-partitioned payment table.
Why is there no payment partitions table in this diagram?
In production Pagila partitions payment by month (payment_p2022_01 and so on), which would add dozens of identical tables to the diagram. The payment table shown here carries the inherited foreign keys; the FAQ source file documents the full partitioned layout.
Explore more schemas
Visualize your own database
Paste your PostgreSQL connection string and get an interactive ER diagram of your own schema in under 10 seconds. No signup required.
Try it free →