Vlad Mihalcea
vladmihalcea.com · Personal blog · on HN since 2014
Vlad Mihalcea, a Hibernate developer advocate and author, writes about Java persistence, SQL, database transactions and performance.
What HN saysCommenters recommend it for high-performance Hibernate advice, including fixing N+1 queries, the hi/lo algorithm, and running integration tests on tmpfs.
44HN people shared it
15linked it in comments
76stories submitted
173story points
1 year agolast shared
2014people per year2026
Most-shared posts
- 1The best UUID type for a database Primary Key5 people · 4 points · first shared 2022 · discussion on HN
- 214 High-Performance Java Persistence Tips – Vlad Mihalcea4 people · 11 points · first shared 2018 · 1 comments on HN
- 3How Does MVCC (Multi-Version Concurrency Control) Work3 people · 2 points · first shared 2018 · discussion on HN
- 4Time to break free from the SQL-92 mindset2 people · 5 points · first shared 2014 · discussion on HN
- 5A beginner’s guide to ACID and database transactions2 people · 4 points · first shared 2014 · discussion on HN
- 6How to get a 10,000 points StackOverflow reputation2 people · 3 points · first shared 2015 · 1 comments on HN
- 7Homepage2 people · first shared 2017
- 8The hilo algorithm2 people · first shared 2016
- 9Why you should pay developers to learn1 people · 10 points · first shared 2015 · 1 comments on HN
- 10A beginner’s guide to Cache synchronization strategies1 people · 7 points · first shared 2016 · discussion on HN
- 1114 High-Performance Java Persistence Tips1 people · 6 points · first shared 2016 · discussion on HN
- 12MySQL Query Optimization with Releem1 people · 5 points · first shared 2025 · discussion on HN
- 13The Anatomy of Connection Pooling1 people · 4 points · first shared 2020 · discussion on HN
- 14How Does the 2PL (Two-Phase Locking) Algorithm Work1 people · 4 points · first shared 2019 · discussion on HN
- 15Twelve Years of Blogging1 people · 4 points · first shared 2025 · 1 comments on HN
What HN people wrote when they linked it
stupidcar · 2017-02-16
I think the problem is that too many developers think of ORMs as a black box that lets them avoid SQL and the DB, rather than a powerful tool for working with them.
Vlad Mihalcea, a Hibernate developer/evangelist, has been doing amazing work improving the project's documentation and providing educational material about how to use it properly without sacrificing performance[1]. I can't recommend his book High-Performance Java Persistence enough: https://leanpub.com/high-performance-java-persistence
For me, his key lesson is that ORMs can be incredibly useful if, and only if, your understanding of SQL and DB performance is good enough that you can use them in a DB-friendly way. It's really simple things like expressing relationships between your domain entities such that the resulting tables can be easily joined. You still get the productivity that comes from skipping loads of JDBC boilerplate, but you don't feel like there's a load of magic between you and the DB.
He also pushes the idea that you should use Hibernate in combination with other DB tools: Liquibase/Flyway for migrations, and JOOQ for optimised queries with lots of joins,or DB-specific work. By having a decent ORM, SQL builder, and migration tool, you can use be flexible depending on the situation. Complex, performance-insensitive business logic can use the domain model from the ORM, whereas API-backing queries can be expressed a single, tightly constrained JOOQ call, and the actual creation and maintenance of…
vladmihalcea · 2021-10-09
I've been using Hibernate for 17 years and never had any performance issue with it.
Want to know my secret? It's very simple. I just read the manual in 2004.
After using it successfully for so long, I wrote a best-seller about how to get the most out of it:
https://www.amazon.com/High-Performance-Java-Persistence-Vlad-Mihalcea…
And, just because afterward I even worked on Hibernate to add all sorts of performance improvements to it, it doesn't mean I don't love SQL. In fact, I happen to run a High-Performance SQL training too:
https://vladmihalcea.com/trainings/high-performance-sql/
Your comment is based on a very common misconception that Hibernate aims to replace SQL. If that were true, then why do you think Hibernate has been offering the createSQLQuery (a.k.a. createNativeQuery) since 2002?
heurisko · 2021-07-18
If speed is one of the things holding you back from testing with the native database, running the database data on a tmpfs mountpoint is worth looking at.
https://vladmihalcea.com/how-to-run-integration-tests-at-warp-speed-wi…
skinkestek · 2021-01-28
See https://vladmihalcea.com/
He has a lot of info on high performance Hibernate and particularly the n + 1 issue.
It should be mostly avoidable.
eranation · 2017-06-10
Excellent post, write ups like this are the reason I keep coming here.
What about the hi/lo algorithm as a middle ground?
https://vladmihalcea.com/2014/06/23/the-hilo-algorithm/
In short, and I hope I don't oversimplify, each "shard" or "cluster" in the database gets a "block" of ids it can then go and assign on their own, the sequential "atomic" increase happens only once per hi "block", lowering the contention.
This gives you nice integers, incremental-ish most of the time.
I like the notion of integers internally and UIID (as integers of course! I would have never saved one as a varchar, I swear! ok, I was a noob... I deserve to be shamed)
Great post all in all!
ramchip · 2024-10-29
Hash join is not a nested loop, it's two separate loops one after the other. This makes a huge difference since the complexity is O(N+M) rather than O(N*M). See these examples:
https://vladmihalcea.com/hash-join-algorithm/
https://vladmihalcea.com/nested-loop-join-algorithm/
w1zard0f0z · 2024-05-06
How about TSIDs? Numerical, half the size, time sorted... https://vladmihalcea.com/uuid-database-primary-key/
ttfkam · 2023-06-26
A shame there's no mention of LATERAL. I use it all the time.
https://vladmihalcea.com/sql-lateral-join/
chromanoid · 2021-04-29
You actually should in the backend, at least when using clustered indices... See also https://vladmihalcea.com/clustered-index/ Last section about "Clustered Index column monotonicity".
Of course a public facing uuid or so is possible, but you want to index this too...
victor106 · 2021-04-12
Lot of Hibernate hate in this thread. This really helped me. Strongly suggest. Also Vlad writes really awesome posts on using Hibernate along with Spring etc.,
https://vladmihalcea.com/courses/
tobyjsullivan · 2021-01-28
Thanks for sharing this.
For anyone else interested, here’s one post he has on the problem: https://vladmihalcea.com/n-plus-1-query-problem/
oftenwrong · 2020-06-14
teddyh · 2016-06-17
For those who don’t know what it is:
https://vladmihalcea.com/2014/06/23/the-hilo-algorithm/
Basically, it optimizes for lots of insert operations by using a composite primary key, one of which is a SERIAL assigned by the server, and the other is a value arbitrarily assigned by the client. This allows a client to assign and use many new unique keys without asking the server for a new value for every individual row.
cogman10 · 2024-06-05
A problem with this approach is it's not monotonical.
Especially if you want to use this thing as an index in a database, you'll run into problems where you try doing middle insertions frequently, which causes fragmentation.
The solution to this problem is making the higher order characters time sorted [1]. You don't need to go all out like uuid, you can have a pretty low resolution. It's more important that new insertions tend to be on the same page. If you have a low frequency insertions then minute resolution is probably good enough. (Minutes since 2000 is an easy calculation).
To implement that here, I'd suggest looking at how base64 or 85 encoders work and use that instead of repeated mods. You can then dedicate the upper bits to a time component and the lower bits can remain random. [2]
[1] https://vladmihalcea.com/uuid-database-primary-key/
[2] https://github.com/mklemm/base-n-codec-java/blob/master/src/main/java/…
pmontra · 2020-03-19
I understand that this is an example so I try to build some context around those queries.
The issue here is that you (apparently) want to guarantee that whoever sees the result of the select (probably a customer) can safely buy the last available book with the update.
This can't be solved in a simple way because minutes can pass between that select and that update. This means that you can't put those queries in a transaction. If you could you should use select for update
https://www.postgresql.org/docs/current/sql-select.html
I used code like update table set counter = counter + 1 / - 1 many times without transactions when all I have to do is to update a counter and nothing else in the system really cares about the value of the counter. If this is not the case, the queries accessing the counter should use some form of locking. A transaction is not enough.
This is the first good guide I found googling for examples
https://vladmihalcea.com/a-beginners-guide-to-database-locking-and-the…