Here is a comprehensive list of technical data modeling interview questions, categorized by skill level. These questions focus on relational (OLTP) and dimensional (OLAP/Data Warehousing) modeling, with a touch of NoSQL for the advanced tier.
I have also included “Expected Answer Bullets” so you know exactly what to listen for.
Beginner Level (Conceptual & Logical Understanding)
Goal: Ensure they understand the basics of keys, normalization, and relationship types.
1. The “Employee Manager” Problem (Relationships)
Question: In an Employees table, how would you model the relationship where one employee manages another? What is this type of relationship called?
- Expected Answer: It is a Recursive (or Self-Referencing) Foreign Key. The table would have an
EmployeeID(Primary Key) and aManagerID(Foreign Key that referencesEmployeeID). This represents a one-to-many relationship (one manager has many employees).
2. Normalization Explainers
Question: Briefly explain 1st, 2nd, and 3rd Normal Form (1NF, 2NF, 3NF) in plain English.
- Expected Answer:
- 1NF: Atomic values (no repeating groups or arrays in a single column).
- 2NF: Must be in 1NF, and every non-key column must depend on the entire primary key (relevant for composite keys).
- 3NF: Must be in 2NF, and no non-key column depends on another non-key column (no transitive dependencies).
3. Natural vs. Surrogate Keys
Question: What is the difference between a natural key and a surrogate key? Give an example of when you would use each.
- Expected Answer:
- Natural Key: A column that already exists in the real world (e.g.,
SSN,ISBN,VIN). Risky because they can change or be reused. - Surrogate Key: An artificially generated unique identifier (e.g., an
INT IDENTITYorUUID). Preferred in data warehouses because it isolates the fact table from changes in the source system.
- Natural Key: A column that already exists in the real world (e.g.,
Intermediate Level (Physical Design & Dimensional Modeling)
Goal: Assess their ability to handle performance, historical data, and warehousing structures.
4. Indexing Strategy
Question: You have a Sales table with 1 billion rows. Users frequently query by Order_Date and Customer_ID. How would you index this table, and what is the danger of creating too many indexes?
- Expected Answer:
- Create a Composite Non-Clustered Index on (
Customer_ID,Order_Date) becauseCustomer_IDis likely highly selective. - Danger: Too many indexes drastically slow down
INSERT,UPDATE, andDELETEoperations (write amplification) because the index must be updated alongside the table.
- Create a Composite Non-Clustered Index on (
5. Star Schema vs. Snowflake Schema
Question: When building a data warehouse, when would you choose a Star Schema over a Snowflake Schema?
- Expected Answer:
- Star Schema: Denormalized dimensions. Preferred for simplicity, faster query performance (fewer joins), and easier use by BI tools.
- Snowflake Schema: Normalized dimensions. Used to save storage space or when dimensions are extremely complex. Downside: More joins = slower queries.
- Key insight to listen for: “Always start with Star and only snowflake if storage is a crisis.”
6. Handling SCD Type 2
Question: A customer changes their address. In a data warehouse, we need to keep the historical address for old orders. How do you model this? (Hint: SCD)
- Expected Answer: This is a Slowly Changing Dimension (SCD) Type 2.
- Add columns:
Start_Date,End_Date(orNULLfor current), andIs_Current_Flag. - Instead of updating the old record, you expire the old row (set
End_Date= yesterday) and insert a new row with the new address, a new surrogate key, andStart_Date= today. This ensures historical fact tables still point to the old surrogate key.
- Add columns:
Advanced Level (Scalability, NoSQL, & Complex Optimization)
Goal: Stress-test their critical thinking on distributed systems, anti-patterns, and enterprise architecture.
7. The Polymorphic Association (Anti-Pattern)
Question: You have an Orders table and a Returns table. You are asked to create a single Notes table that can attach comments to either an Order or a Return. The junior developer proposes a table with columns: NoteID, Note_Text, Parent_Type (‘Order’ or ‘Return’), and Parent_ID. Why is this a bad practice, and how would you fix it?
- Expected Answer:
- Why it’s bad: You cannot enforce a Foreign Key constraint because the
Parent_IDreferences two different tables. This breaks referential integrity. - Fix: Create two separate junction tables:
Order_NotesandReturn_Notes. Or, use concrete super-types (create a genericEventtable that both Orders and Returns inherit from, then link Notes toEvent_ID).
- Why it’s bad: You cannot enforce a Foreign Key constraint because the
8. Eventual Consistency vs. Strong Consistency
Question: You are modeling a microservices architecture. You have a Product Catalog service and an Inventory service. How do you model the data relationship between these two services if they use separate databases, and what consistency model do you choose?
- Expected Answer:
- Modeling: There is no foreign key across databases. You store the
Product_ID(as a value) in the Inventory service, but do not enforce a physical relationship. - Consistency: You must use Eventual Consistency via asynchronous messaging (e.g., Kafka, SQS). If a product is deleted in Catalog, an event is published to update Inventory. You cannot use a distributed transaction (2PC) because it creates tight coupling and availability issues.
- Modeling: There is no foreign key across databases. You store the
9. Query Optimization using Execution Plans
Question: You run a query that joins a 10-million-row Fact_Sales table to a 10,000-row Dim_Product table. The query takes 45 seconds. You look at the execution plan and see a “Hash Match” join and a “Key Lookup” (Clustered) taking 80% of the cost. How do you fix this?
- Expected Answer:
- Problem: The “Key Lookup” means the index used does not “cover” the query. The database is finding the rows in the index, then jumping back to the clustered table to get the remaining columns.
- Fix 1: Create a Covering Non-Clustered Index on
Dim_Productthat includes all the columns requested in theSELECTandWHEREclauses (or useINCLUDEfor the heavy text columns). - Fix 2: If filtering heavily, change the join order using
FORCE ORDERor rewrite the query to push filters into a subquery before the join (reduce the Hash Match bucket size).
10. Designing for Time-Series Data (Partitioning)
Question: You are modeling a table for IoT sensor data that will ingest 1 million rows per hour. Retention policy requires keeping data online for 3 years. What physical database design technique is mandatory for this scenario, and how does it impact your key design?
- Expected Answer:
- Technique: Range Partitioning (usually by date). You should partition the table by the
Event_Timecolumn (e.g., daily or monthly partitions). - Key Design: The Primary Key must include the partition key (e.g.,
PRIMARY KEY (Sensor_ID, Event_Time)). This creates a composite key that ensures uniqueness within a partition. - Bonus Insight: This allows for Partition Switching (fast loading of new data) and Partition Truncating (instant deletion of old data without locking the table).
- Technique: Range Partitioning (usually by date). You should partition the table by the
11. The Polymorphic Contact Manager (Anti-Pattern Identification)
Question: You are reviewing a legacy database design. The team has a Person table with a PersonID. They also have a ContactManager table with the following columns: ContactManagerID (PK), PersonID (FK to Person), ContactID (INT), and ContactType (VARCHAR check constraint: ‘Email’, ‘Phone’, ‘Address’).
The logic is: if ContactType = ‘Email’, the ContactID references the Email table; if ‘Phone’, it references the Phone table; if ‘Address’, it references the Address table.
What is this design pattern called? Is this an ideal approach for a relational database? If not, explain the specific technical flaws and provide two alternative solutions to fix this design.
Expected Answer:
- Beginner Level (Awareness):
- Pattern Name: “Polymorphic Associations” or “Generic Foreign Keys.”
- Initial Assessment: “I don’t think this is a good idea, because I can’t draw a proper ER diagram for it. It feels like the database can’t enforce rules properly.”
- Intermediate Level (Flaw Identification):
- Is it ideal? No, this is considered an anti-pattern in relational modeling.
- Specific Technical Flaws:
- No Referential Integrity: You cannot define a Foreign Key constraint on
ContactIDbecause it points to three different tables based on theContactType. The database cannot guarantee thatContactID123 actually exists in theEmailtable whenContactType= ‘Email’. - Complex Querying: To retrieve a person’s contact info, you must write complex
CASEstatements,UNIONqueries, or join all three tables andCOALESCEthe results. You cannot use simpleINNER JOINs. - Indexing Inefficiency: A single index on
ContactIDis inefficient because the ID values across the three parent tables are semantically different and may overlap. - Constraint Limitations: You cannot enforce type-specific rules (e.g., requiring an
Email_Addressto beNOT NULLor aPhone_Numberto have aCountry_Code) because theContactManagertable only holds generic IDs.
- No Referential Integrity: You cannot define a Foreign Key constraint on
- Advanced Level (Solutions & Trade-offs):
- “To fix this, I would propose two solutions depending on the use case:”
- Solution A: Supertype/Subtype (Best for Transactional/OLTP systems)
- Create a master
Contactstable with aContactID(PK) andContactType. - Change the
Persontable to have an FK directly referencing this newContacts.ContactID. - Change the
Email,Phone, andAddresstables so their Primary Key is not auto-generated. Instead, theirContactIDacts as both the Primary Key and a Foreign Key back to the masterContactstable. This enforces that every subtype record has a valid master record, and maintains a hard FK between Person and Contact.
- Create a master
- Solution B: Multiple Explicit Foreign Keys (Simpler, but less extensible)
- Remove the
ContactManagertable entirely. - Add three nullable columns directly to the
Persontable:EmailID(FK to Email),PhoneID(FK to Phone), andAddressID(FK to Address). - This allows the database to enforce strict referential integrity for each type individually.
- Drawback: Requires schema changes (new columns) every time a new contact type (e.g.,
SocialMediaID) is introduced.
- Remove the
- Expert Level (Contextual Awareness):
- “Before choosing a fix, I need to clarify the business requirement. If this is a Data Warehouse (OLAP), I wouldn’t use either of those relational solutions. I would likely denormalize the data and store the actual Email, Phone, and Address values directly in a wide
Dim_Persontable (with NULLs), because we don’t enforce Foreign Keys in dimensional models, and we prioritize query performance over storage normalization.”
- “Before choosing a fix, I need to clarify the business requirement. If this is a Data Warehouse (OLAP), I wouldn’t use either of those relational solutions. I would likely denormalize the data and store the actual Email, Phone, and Address values directly in a wide
- Is solution A still polymorphic?
- Follow-up Question (Optional):
- “In Solution A, we introduced a master
Contactstable. Is this still considered a polymorphic association? Why or why not?”
Expected Answer:
Beginner: “I think it is, because we still have aContactTypecolumn.”
Intermediate: “No, it is not polymorphic anymore. TheContactIDin thePersontable now references only one table (Contacts), so we can enforce a proper Foreign Key constraint. TheContactTypeis just an attribute now.”
Advanced (The “Aha!” insight):
“It is no longer polymorphic because we have removed the ambiguity. In the original design, theContactIDmeant three different things depending on the row, that was the polymorphism. In Solution A, theContactIDalways means ‘a row in the Contacts table.’ The type column simply tells you which child table to join to for the details. This is standard relational inheritance modeling, often called Single Table Inheritance at the physical level, but strictly speaking, it is a Supertyping pattern, not a polymorphic association.”
- “In Solution A, we introduced a master
- Pro Tip for your interview: The best senior candidates won’t just stop at fixing the FK, they will ask you “What queries run against this?” because if you rarely query contacts across all types, Solution B (3 nullable FKs) might actually be faster and simpler than Solution A (which requires an extra join to the master table for every contact lookup). The expert knows there is no “perfect” solution, only trade-offs based on access patterns.
12. Handling Shared Contacts (Many-to-Many Scenario)
Question: Building on the previous Supertype/Subtype model (Solution A), we now have a new business requirement: An Address can be shared by multiple People (e.g., family members living at the same residence, or a business address used by many employees).
However, an Email and a Phone number are still considered unique to a single Person (cannot be shared).
Given this mixed requirement, how would the Supertype/Subtype model need to be altered? Walk through the specific structural changes and explain why this is now a different relationship pattern.
Expected Answer:
- Beginner Level (Awareness):
- “I would just put the same
ContactIDinto multiplePersonrecords. So, if two people share an address, they both have the sameAddressIDin theirPersonrow.” - Interviewer note: This shows they understand the concept but haven’t yet considered the data integrity or modeling implications. It also breaks the uniqueness assumption of the
Contactstable if we use the original foreign key approach.
- “I would just put the same
- Intermediate Level (Structural Understanding):
- The Problem with the Original Model:
- In Solution A,
Personhas a one-to-many relationship withContacts(one Person, many Contacts). - If an Address is shared, we now have a many-to-many relationship between
PersonandContactsfor that specific ContactType. - We cannot simply put the same
ContactIDin multiplePersonrows unless we change the relationship and remove the FK constraint fromPerson, which breaks referential integrity.
- In Solution A,
- The Fix:
- Remove the
PersonIDcolumn from theContactsmaster table. - Create a junction (bridge) table called
PersonContactwith a composite key of (PersonID,ContactID). PersonIDis an FK toPerson.ContactIDis an FK toContacts.- This allows any Person to link to any Contact, and any Contact to link to multiple People.
- Remove the
- The Problem with the Original Model:
- Advanced Level (Constraints & Business Logic Enforcement):
- “The structural fix is a junction table, but that alone isn’t enoughโI need to enforce the business rules at the database level to prevent emails and phones from being shared, while allowing addresses to be shared.”
- How to enforce this:
- Option A (Database Constraints): Add a
Is_Sharedboolean column to theContactsmaster table. Then create a unique constraint on (ContactID,PersonID) in the junction tableโbut that doesn’t solve the sharing restriction. - Option B (Trigger or Application Logic – Practical approach): The junction table itself doesn’t prevent sharing. To enforce the rule, you would:
- Allow multiple
PersonContactrows for the sameContactID. - But, add a
Max_SharedorIs_Shareablecolumn to theContactTypelookup table (or directly onContacts). - Then, use a trigger (or application-level validation) that checks: “If
ContactType= ‘Email’ or ‘Phone’, count the number of rows inPersonContactfor thisContactIDand throw an error if > 1.” - Alternative: If using a modern RDBMS (like PostgreSQL), use a partial unique index:sqlCREATE UNIQUE INDEX idx_unique_person_contact ON PersonContact (ContactID) WHERE ContactType IN (‘Email’, ‘Phone’);(Note: This requires the
ContactTypeto be denormalized intoPersonContactor a join in the index, which may not be supported by all databases.)
- Allow multiple
- Option C (Schema Separation – Cleanest but more tables):
- Keep the many-to-many junction for
Addressesonly:PersonAddress(PersonID,AddressID). - Keep the one-to-many FKs for
EmailandPhonedirectly on thePersontable (or via a non-shared junction). - This physically enforces the rule without triggers, because the junction table allows sharing, while the direct FK does not.
- Keep the many-to-many junction for
- Option A (Database Constraints): Add a
- Expert Level (Contextual Trade-offs):
- “Before implementing Option B or C, I need to ask: How often do addresses change? If addresses are frequently updated and shared by hundreds of employees, I might consider a normalized approach (Option C) to save storage and maintain single points of update. However, if this is a Data Warehouse, I’d ignore the normalization entirely and denormalize the shared address into each Person’s row to avoid complex joins in BI reports. The ‘ideal’ model depends entirely on whether this is an OLTP system with strict write integrity or an OLAP system with read performance priorities.”
- “Additionally, I would ask: If an address is shared, and one person updates it, should it update for everyone? That dictates whether we use a ‘shared reference’ (junction table) or copy the address value directly into each person’s row.”
Intermediate Level (Relationship Evolution & Role-Based Modeling)
1B. The Employee Manager Problem โ Extended (Multiple Manager Types)
Question:
Building on the previous “Employee Manager” model, the business has introduced a new requirement:
“Each employee now has three types of managers:
- Direct Manager (the person they report to daily โ the original requirement).
- Dotted-Line Manager (a secondary manager from a different department who provides project oversight).
- Location Manager (the manager responsible for the physical office/branch where the employee sits).”
How would the data model need to change to accommodate these three distinct management relationships? Walk me through the trade-offs of at least two different modeling approaches.
Expected Answer:
- Beginner Level (Awareness):
- “I would just add three columns to the
Employeestable:ManagerID,DottedLineManagerID, andLocationManagerID. All three would be Foreign Keys that referenceEmployeeID.” - Interviewer note: This works functionally but shows a lack of foresight. It hard-codes the relationship types into the schema, meaning any new manager type (e.g., “Project Manager,” “Regional Manager,” “HR Partner”) requires an ALTER TABLE to add a new column.
- “I would just add three columns to the
- Intermediate Level (Normalization & Flexibility):
- Problem with the 3-column approach: It’s not extensible. If we add a 4th or 5th type of manager, we have to change the table structure, which requires downtime, migration scripts, and code changes.
- Better Approach โ Junction Table with Roles:
- Remove
ManagerIDcolumns from theEmployeestable entirely. - Create a junction table called
EmployeeManagerorManagementStructurewith the following columns:EmployeeID(FK to Employees) โ The subordinate.ManagerID(FK to Employees) โ The supervisor.RelationshipType(VARCHAR or INT FK to a lookup table) โ Values: ‘Direct’, ‘DottedLine’, ‘Location’.
- This creates a many-to-many relationship between Employees and themselves, with a role/type discriminator.
- Why this is better: Adding a new manager type (e.g., “Project Manager”) simply requires inserting a new row into a
RelationshipTypelookup table. No schema changes required.
- Remove
- Constraint Consideration:
- If every employee must have exactly one Direct Manager, you can enforce this with a unique constraint on (
EmployeeID,RelationshipType) whereRelationshipType= ‘Direct’, or use a filtered/partial index. Alternatively, enforce it at the application level or via a trigger.
- If every employee must have exactly one Direct Manager, you can enforce this with a unique constraint on (
- Advanced Level (Temporal Modeling, Hierarchy Depth, & Edge Cases):
- “The junction table is the right structural move, but I have several follow-up questions and enhancements:”
- 1. Temporal Tracking (Historical Auditing):
- “Does the business need to track when a management relationship changed? For example, if John had a different dotted-line manager last quarter, we might need to preserve that history for performance reviews or organizational audits.”
- Solution: Add
Start_DateandEnd_Date(orIs_Current_Flag) to theEmployeeManagerjunction table. This makes it an SCD Type 2 structure for management relationships.
- 2. Circular Reference Prevention:
- “We must prevent circular reporting structures (e.g., A manages B, B manages C, and C manages A), which can cause infinite loops in queries and reporting.”
- Solution: This cannot be fully enforced by standard SQL constraints. It requires either:
- Application-level validation before insert/update.
- A trigger that checks for cycles using a recursive CTE and rolls back the transaction if a cycle is detected.
- Database-specific features: Some databases (like PostgreSQL with
WITH RECURSIVE) can enforce this via exclusion constraints, but typically it’s handled in the business logic layer.
- 3. Depth & Hierarchy Reporting:
- “How deep does the management chain go? If we need to report on the entire organizational tree (e.g., ‘show me all employees under VP of Engineering’), we need to consider recursive query performance.”
- Solution:
- For transactional systems, use recursive CTEs to traverse the hierarchy.
- For reporting/OLAP systems, consider denormalizing with a closure table (precomputing all ancestor-descendant paths) or materializing the hierarchy path (e.g., storing a
Pathstring like/CEO/VP/Director/Employee).
- 4. Edge Cases:
- “Can an employee be their own manager? (Should be prevented.)”
- “Can an employee have no manager (e.g., the CEO)? How do we represent NULL values in the junction table?”
- “What happens when a manager leaves the company? Do we cascade delete, or do we require the manager to be reassigned first?” (This shows they think about data integrity and business processes.)
- Expert Level (Organizational Modeling & Graph Databases):
- “If management relationships are a core domain concept with multiple types, changing over time, and we frequently query the entire organizational tree, I would consider using a Graph Database (like Neo4j) instead of a relational model.”
- “In a graph model, Employees are nodes, and management relationships are edges with properties (Type, Start_Date, End_Date). This makes recursive queries (‘find all subordinates of X at any depth’) O(1) in traversal complexity and avoids expensive recursive CTEs in SQL.”
- “However, if we must stay in SQL, I’d evaluate whether a Closure Table is worth the storage overhead for faster reads, or if we can tolerate recursive CTEs for occasional queries.”
| Question | Correct Answer |
|---|---|
| Is this design polymorphic? | NO. Polymorphism requires a single FK pointing to multiple tables. Here, it points to only one. |
| What is this pattern called? | Supertype/Subtype (or Table Inheritance). |
| What is the discriminator column for? | Descriptive metadataโit tells you which subtype table contains the details, but it does not route the FK. |
| Can you enforce referential integrity? | YES. A hard FK can be placed from PersonContact.ContactID to Contacts.ContactID. |
| Is this a good design? | YES. It is the industry-standard relational solution for this problem. |
Bonus: “Whiteboard” Scenario (For all levels)
Give them a piece of paper and ask:
“Draw a logical data model for a
University Registration System. We haveStudents,Professors,Courses, andRooms. A Student can enroll in many courses; a Course is taught by one Professor; a Course meets in one Room.”
- Beginner check: Do they draw the 4 tables and establish Foreign Keys?
- Intermediate check: Do they realize a
Student_Coursejunction table is needed for the many-to-many relationship? - Advanced check: Do they ask clarifying questions? (e.g., “Can a room be used by multiple courses at different times? If so, we need a Time slot dimension.”). The advanced candidate does not just draw; they define the grain.










