Java Backend / Database Interview Preparation

Interview Questions on Database

Complete document converted into a clean, searchable HTML study guide. Source tables are recreated as real HTML tables and the original embedded images are preserved without replacing the document's written content.

Interview Questions on Data Base Prepared by Srikanth Mamillapalli

1. How to increase the performance or tune the queries

Understand the Query

What data is being requested?
How frequently is it run?
How big are the tables involved?

Use EXPLAIN / EXPLAIN ANALYZE

Use the database’s query plan tool to see how the query is executed.

Which indexes are being used
If full table scans are happening
Estimated rows being scanned

Optimize the SELECT Clause

Add or Improve Indexes

Create indexes on columns used in WHERE, JOIN, GROUP BY, or ORDER BY

Rewrite the Query

Sometimes breaking a complex query into smaller steps (e.g., with CTEs or temp tables) helps.
Also:
Replace subqueries with joins (or vice versa), depending on which performs better.
Use EXISTS instead of IN when appropriate.

Use Proper Joins

Make sure joins use indexed keys and are selective:

Limit Result Set

Analyze and Vacuum (PostgreSQL-specific)

Consider Materialized Views or Caching

Database-Specific Tools

Each DB has tools:

MySQL: EXPLAIN, SHOW PROFILE
PostgreSQL: EXPLAIN (ANALYZE, BUFFERS), pg_stat_statements
SQL Server: Execution Plans, Query Store
Oracle: SQL Trace, TKPROF

What is index and what are the types of index

An index in a database is a data structure that improves the speed of data retrieval operations on a table at the cost of additional storage and write time

2.1 Why Use Indexes?

Speed up SELECT queries.
Improve JOIN, WHERE, ORDER BY, GROUP BY operations.
Reduce full table scans.
At a cost of:
Slower write operations.
Increased storage usage.

2.2 Types of Indexes in PostgreSQL

Index TypeDescriptionUse Case
B-Tree IndexDefault index type. Balanced tree structure. Supports equality and range queries.=, <, >, BETWEEN, ORDER BY.
Hash IndexIndex based on hash values. Supports equality (=) lookups only.Exact match queries, e.g., WHERE user_id = 42.
GIN (Generalized Inverted Index)Efficient for indexing array values, JSONB, and full-text search.Full-text search or JSONB fields like tags @> ['sql'].
GiST (Generalized Search Tree)Supports custom strategies for complex data types.Geometric data, ranges, full-text, and fuzzy search.
SP-GiST (Space-Partitioned GiST)Better suited for non-balanced trees and partitioned data.Hierarchical or spatial data (e.g., quadtrees).
BRIN (Block Range Index)Summarizes ranges of data blocks. Compact and efficient for large tables.Very large tables with naturally sorted data.
Expression IndexIndexes based on the result of an expression.CREATE INDEX ON users (lower(email)).
Partial IndexIndex only a subset of rows matching a condition.WHERE is_active = true. Reduces size, speeds up queries.
Unique IndexEnforces uniqueness on one or more columns.email or username must be unique.
Composite IndexIndex on multiple columns. Order matters.CREATE INDEX ON orders (user_id, created_at);.
Covering Index (INCLUDE)Stores additional columns in the index to avoid lookups. (PostgreSQL 11+)CREATE INDEX ON users (id) INCLUDE (email, name);

2.3 Interview Question

QuestionSample Answer
When do you use a clustered index?When you frequently query data by primary key or a column that requires sorting.
Can a table have multiple clustered indexes?No, only one clustered index is allowed per table.
What about non-clustered indexes?You can create multiple non-clustered indexes on different columns to speed up searches.

What is the cursor and refcursor in pl/sql

In databases, cursors and refcursors are tools used in procedural SQL (like PL/pgSQL in PostgreSQL or PL/SQL in Oracle) to work with query results row-by-row, especially inside stored procedures or functions.

Cursor :

A cursor is a database object used to retrieve a set of rows returned by a query and process them one at a time. It's useful when you need to perform operations on each row individually.

How it works:

Declare the cursor (based on a query).
Open the cursor (execute the query).
Fetch rows from the cursor (one or more at a time).
Close the cursor when done.
DECLARE
my_cursor CURSOR FOR SELECT id, name FROM users;
user_record RECORD;
BEGIN
OPEN my_cursor;

LOOP

FETCH my_cursor INTO user_record;
EXIT WHEN NOT FOUND;

-- Do something with user_record

END LOOP;
CLOSE my_cursor;
END;
Ref Cursor : Reference Cursor

A refcursor is a cursor variable—a pointer or reference to a result set. It's more dynamic and flexible than a regular cursor and is often used when you want to return a result set from a function or procedure.

Why use refcursors?

You can pass them around as variables.
You can return them from functions.
Great for client applications that need to fetch large or variable result sets.
Example returning a refcursor:
CREATE OR REPLACE FUNCTION get_users()

RETURNS refcursor AS $$

DECLARE
ref refcursor;
BEGIN
OPEN ref FOR SELECT * FROM users;
RETURN ref;
END;
$$ LANGUAGE plpgsql;

Image from Database Interview document

Triggers in database:

A trigger is a special kind of stored procedure that automatically runs (is "triggered") in response to certain events on a table or view.

When Do Triggers Fire?

Triggers can be fired:

BEFORE an operation (e.g., before inserting a row)
AFTER an operation (e.g., after updating a row)
INSTEAD OF an operation (used mostly on views)

Use Cases for Triggers

Logging/auditing changes
Validating or enforcing complex rules
Automatically updating timestamps
Denying certain operations
Cascading updates/deletes (in custom ways)

IN,OUT,IN_OUT parameters in database stored procedure

IN Parameter

Input only: Passes a value into the procedure.

Value is read-only inside the procedure.

Default type if nothing is specified.

Cannot be modified within the procedure (any changes won't reflect outside).

OUT Parameter

Used to return a value from the procedure to the caller.

Cannot be used to pass input into the procedure.

Acts like a return variable.

INOUT Parameter

Works both ways:

Passes a value into the procedure.

Allows the procedure to modify it and return the updated value.

Raise an exception in stored procedure

RAISE EXCEPTION 'Balance cannot be negative';

PostgreSQL lets you use RAISE NOTICE, RAISE WARNING, or RAISE EXCEPTION

Image from Database Interview document

How to handle errors/exception in stored procedure
BEGIN

-- normal code

EXCEPTION

WHEN <exception_name> THEN

-- handle the exception

WHEN OTHERS THEN

-- handle any other exception

END;
Different types of database types

Image from Database Interview document

Different types of joins

Image from Database Interview document

execute a stored procedure from java/springboot/jpa

To execute a stored procedure from Java/Spring Boot/JPA, you have multiple ways to achieve this depending on the JPA provider (e.g., Hibernate) and the type of procedure (i.e., IN, OUT, or INOUT parameters).

Session.createNativeQuery: Execute stored procedures using native SQL.
CallableStatement: Use for IN, OUT, or INOUT parameters when more control over execution is needed.
Spring Data JPA @Query with @Procedure: Call stored procedures through the @Procedure annotation (works if you're using Spring Boot and Spring Data JPA).
EntityManager: Use StoredProcedureQuery to execute stored procedures in a JPA-native way.
Image from Database Interview document

Image from Database Interview document
Image from Database Interview document

Different queries

Select dept_id, max(sal) from employee group by dept_id;
Select * from emp where manager_id is null;
Select a.name as employee,b.name as manager from emp a left outer join
Emp b on a.manager_id=b.manager_id;
Select dept_id,count(*) from emp group by email having count(*) >1;
Select emp_id, salary, rank() over (order by sal desc) as salary_rank from emp;
Update-time< now – interval 30 day;

CTE common table expressions

A CTE (Common Table Expression) in databases is a temporary result set that you can reference within a SELECT, INSERT, UPDATE, or DELETE statement. It's defined using the WITH keyword and is often used to improve readability and structure of complex queries, especially those involving recursion or subqueries.

WITH cte_name AS (
SELECT ...

)

SELECT * FROM cte_name;
WITH cte1 AS (
SELECT ...

),

cte2 AS (

SELECT ...

)

SELECT * FROM cte2;

Benefits of Using CTEs

Makes queries more readable and maintainable
Can be recursive (great for hierarchical/tree data)
Allows you to reference the CTE multiple times in the main query

SnowFlake and Databrics

Snowflake: Snowflake is a cloud-based data warehouse platform. It provides a Software-as-a-Service (SaaS) solution that allows companies to store, process, and analyze large volumes of structured and semi-structured data.

Key Features:

Cloud-native architecture
Built for AWS, Azure, and GCP.
Separates storage and compute, so you can scale them independently.
Multi-cluster compute
Automatically scales to handle concurrency.
No performance bottlenecks with multiple users.
Zero management
No indexing, tuning, or infrastructure to manage.
Fully managed by Snowflake.
Data Sharing
Securely share data across organizations without data movement.
Support for multiple data types
Handles structured data (tables) and semi-structured (JSON, Avro, Parquet).
SQL-first
Optimized for SQL workloads; very friendly to analysts and BI tools.

Use Cases:

Business Intelligence (BI) and reporting.
Data warehousing.
Data sharing between organizations.
Real-time analytics (to some extent).

Databricks

Databricks is a data lakehouse platform that combines the best features of data lakes and data warehouses. It’s built on top of Apache Spark and supports advanced data engineering, data science, and machine learning workflows.

Use Cases:

Data science & ML pipelines.
ETL/ELT processing.
Big Data analytics.
Real-time streaming analytics.
Unified analytics from raw to curated data.

JPA Repository and CURD Repository

public interface PagingAndSortingRepository<T, ID> extends CrudRepository<T, ID>

@NoRepositoryBean Annotation to exclude repository interfaces from being picked up and thus in consequence getting an instance being created.

public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> {

CrudRepository: Provides basic CRUD (Create, Read, Update, Delete) operations

Key Methods:
save(S entity)
findById(ID id)
findAll()
deleteById(ID id)
deleteAll()

Use CrudRepository when you only need simple CRUD functionality.

JpaRepository:

Extends: PagingAndSortingRepository, which itself extends CrudRepository
Purpose: Adds JPA-specific features + pagination and sorting capabilities.
Use JpaRepository when you need advanced JPA operations, pagination, or batch processing.
JpaRepository → PagingAndSortingRepository → CrudRepository

Image from Database Interview document

Pagination logic

TypedQuery<Campaign> typedQuery = entityManager.createQuery(query);
final int pageSize = (searchDto.getPageSize() > 0 ? searchDto.getPageSize() : Integer.MAX_VALUE);
final int pageNumber = Math.max(searchDto.getPageNumber(), 1);
typedQuery.setFirstResult((pageNumber - 1) * pageSize);
typedQuery.setMaxResults(pageSize);
countQuery.select(criteriaBuilder.count(fromCount));
Long totalElements = entityManager.createQuery(countQuery).getSingleResult();
final List<Campaign> list = typedQuery.getResultList();
final List<CampaignSearchOutDto> result = new ArrayList<>();

if (list != null) {

for (Campaign campaign : list) {

result.add(buildDto(campaign));

}

}

int availablePages = totalElements.intValue() / pageSize + (totalElements.intValue() % pageSize != 0 ? 1 : 0);
Integer nextPage = pageNumber + 1 == availablePages ? null : pageNumber + 1;
Integer nextItems = nextPage == null ? 0 : totalElements.intValue() - (pageSize * (pageNumber + 1));
Integer previousPage = availablePages == 1 ? null : pageNumber - 1;
Integer previousItems = previousPage == null ? 0 : pageSize * pageNumber;
logSpentTime("searchCampaignsByPaginationFilterV2", startTime);
LOGGER.debug(LOG2_, result, searchDto);
return new PaginatedOutDto<CampaignSearchOutDto>(totalElements.intValue(), availablePages, nextPage, previousPage, nextItems, previousItems, availablePages - 1,
result);

Transaction

A transaction is a sequence of one or more operations that must all be completed successfully; otherwise, none of them should be applied. It follows the ACID principles:
Atomicity: All or nothing
Consistency: Valid state before and after
Isolation: Transactions don’t interfere
Durability: Once committed, it stays

Where to Maintain Transactions?

Best Practice: Service Layer in Spring Boot

Why at the service layer?

Business logic usually lives in the service layer, which coordinates multiple DAOs or repositories.
Keeping transaction boundaries in services provides modularity and reusability of data access code.
Allows control over transaction scope (begin/commit/rollback) where it logically makes sense.

Backed by: Relational Database (like MySQL/PostgreSQL)

Relational databases natively support ACID transactions.
Use database's transaction capabilities through Spring's abstraction.

Propagation (Spring Transaction Propagation Behavior)

Propagation defines how transaction boundaries behave when a method is called within an existing transaction.

Propagation TypeDescription
REQUIREDJoins existing transaction, or creates a new one if none exists (default).
REQUIRES_NEWSuspends current transaction, starts a new one.
SUPPORTSJoins existing if present, else non-transactional.
NOT_SUPPORTEDSuspends any existing transaction, runs non-transactionally.
MANDATORYMust be called within an existing transaction, else exception.
NEVERMust be called outside a transaction, else exception.
NESTEDRuns in a nested transaction (uses savepoints), if a transaction exists.

Isolation Levels (Database Transaction Isolation)

Isolation controls how visible the changes made in one transaction are to others, affecting data consistency and concurrency.

Isolation LevelDescriptionIssues Prevented
READ_UNCOMMITTEDAllows dirty reads. Least isolation.None
READ_COMMITTEDPrevents dirty reads. Default in many DBs.Dirty reads
REPEATABLE_READPrevents dirty and non-repeatable reads.Dirty, non-repeatable reads
SERIALIZABLEHighest isolation, full ACID.All (dirty, non-repeatable, phantom)

Common Mistakes to Avoid

MistakeWhy it's bad
Using @Transactional on private methodsSpring AOP won’t proxy it, so transaction won't apply
Putting transactions in ControllerViolates separation of concerns, makes debugging hard
Not handling exceptionsCould result in partial commits if not handled properly
Using NoSQL DBs without transaction supportMay cause data inconsistency in multi-step updates

What is @Transactional in Spring?

Maintain transactions in the service layer using @Transactional backed by a relational database. This is accurate, scalable, and aligns with both Spring's architecture and database ACID guarantees.

@Transactional is a Spring annotation used to manage transaction boundaries declaratively. It ensures that the logic inside a method runs within a database transaction, and can be committed or rolled back based on success or failure.

What are the default properties of @Transactional?

Defaults:

Propagation: REQUIRED
Isolation: DEFAULT
readOnly: false
rollbackFor: Only unchecked exceptions (RuntimeException and Error)

What happens if an exception is caught and not rethrown in a @Transactional method?

Spring only rolls back on uncaught runtime exceptions. If you catch and swallow the exception, the transaction won’t roll back.

To manually trigger rollback:

TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();

What happens when one @Transactional method calls another in the same class?

It bypasses the proxy — transaction will not apply. Solution: Move the method to another bean or use AspectJ weaving instead of proxy-based AOP.

What is the role of readOnly=true?

@Transactional(readOnly = true)

Used for read-only operations, it:

Can avoid flush and dirty checks
Optimizes performance (especially in Hibernate)

How is transaction managed in Spring Boot JPA?

Uses PlatformTransactionManager (like JpaTransactionManager)
Auto-configured by Spring Boot if using spring-boot-starter-data-jpa
Integrates with Hibernate, EntityManager, and DataSource

How does @Transactional work internally?

Spring uses AOP proxies (JDK or CGLIB) to intercept method calls and apply transaction behavior before and after the method execution.

Rollback example

@Transactional(rollbackFor = { CustomBusinessException.class, IOException.class })

What is transaction propagation?

When a method in one service calls a method in another service, we must be careful whether the second method:
continues using the existing transaction or
starts a new one or
suspends the current one temporarily.

This behavior is controlled by the propagation setting inside @Transactional.By default, Propagation.REQUIRED is used — meaning if a transaction exists, it will join it, else it creates a new one.

↑ Back to top