Over-indexing
Nikolay Samokhvalov
?? Let's make *your* Postgres healthy and awesome: [email protected] // I stand with Ukraine ???? // Postgres.AI founder; PostgreSQL contributor; Postgres.FM co-host // Freediver
I post a new PostgreSQL "howto" article every day. Join me in this journey – subscribe here or on X, provide feedback, share!
Everyone knows that each additional index is going to slow down writes (INSERT, UPDATE – unless it's HOT). But bear with me today and I promise you'll be very surprised.
Indexes and write overhead
Obviously, if you create a new index, then with each statement that produces new row versions (INSERT, UPDATE), Postgres needs to update this index too – this means, write statements are going to take longer to execute.
For UPDATEs, there is a special optimization – HOT updates, Heap-Only-Tuple updates – that might let Postgres avoid such overhead. This can happen if two conditions are met:
Docs: Heap-Only Tuples (HOT).
And in this article I consider a less trivial situation, in which trying to optimize the index set, we're losing HOT completely (meaning that UPDATEs become slower):
Leaving HOT updates aside, the bottom line is pretty straightforward: the more indexes you have, the slower the writes.
What to do: avoid over-indexing, add new indexes wisely, perform index maintenance regularly, dropping unused and redundant indexes.
Indexes and planning time
Now, let's look at some less straightforward cases.
Here is a benchmark that demonstrates that with each extra index, the planning time of a simple SELECT (a PK lookup) noticeably degrades (thanks to Adrien Nayrat for the great tip about planning time):
Compared to the execution time:
– the table with 1 index has a planning time that is more than 4x better, and in this particular case, it's significantly higher than the execution time.
This happens because for each index, Postgres planner needs to analyze more options for execution. Here is a flamegraph for the same query on the same table with 32 indexes (source):
The most significant negative effect on overall latency can be observed for simple SELECTs, where execution time is low and, with a lot of indexes, might be much lower than the planning time.
What to do:
领英推荐
Indexes and fastpath=false (LWLock:LockManager contention)
Have you noticed on the pictures above that when we reach index count 15, the nature of the curves changes, showing a worse degradation than the linear trend that was observed before?
Let's understand why this happens and how to deal with it.
For a single table PK lookup, when executing a query (and planning too - it's enough to run a plain EXPLAIN without executing it to see), Postgres acquires AccessShareLock on the table and all its indexes. This can be surprising. Corresponding source code: plancat.c.
How to check it – assuming we have a table t1:
select pg_backend_pid(); -- remember PID begin; explain select from t1 where id = 1; -- and keep tx open
select * from pg_locks where pid = {{PID}}; -- use the PID above
You will see that for N indexes on t1, N+1 AccessShareLock relation-level locks have been acquired.
For first 16 locks, you'll see true in the pg_locks.fastpath column. For 17th and further, it is going to be false. This threshold is hard-coded in constant FP_LOCK_SLOTS_PER_BACKEND. When fastpath=false, Postgres lock manager uses a slower, but more comprehensive method to acquire locks. Details can be found here.
In a highly concurrent environment , if we have fastpath=false locks, we might start observing LWLock contention, sometime a serious one – a lot of active sessions with wait_event='LockManager' (or lock_manager in PG13 or older) in pg_stat_activity.
This might happen both on the primary or on replicas, when two conditions are met:
The threshold FP_LOCK_SLOTS_PER_BACKEND=16 is, as already mentioned, hard-coded. Per October 2023, there is an ongoing discussion in -hackers to review this constant (thanks, Tomas Vondra , for drafting the patches).
What to do?
A couple of good reads on this topic:
Marathon progress: ▓???????????????? 4.93%
This series is also available in Markdown form: https://gitlab.com/postgres-ai/postgresql-consulting/postgres-howtos
?Backend Developer Nodejs | Database Optimization | Software Solution Architect | OWASP | AWS SAA at C2C Techhub?
7 个月great post