Some selects are being executed over 500k times.
A Person cannot run a query that many times without getting really, really bored.
A Program will run a query that many times perfectly happily.
My first guess - "1+N Query" Model.
Sometimes adopted by Object Relational Mapping tools (ORMs) and possibly unknown to naïve Developers who don't bother to check what their shiny, new, ORM is actually doing, this is where the program/ORM pulls records one-by-one, based on a list of record IDs that it ran in the previous query.
Instead of
select id, a, b, c, d
from ...
where [complex conditions] // say 1000 rows
it executes
select id from ... where [complex conditions] // 1000 IDs
then
select a, b, c, d from ... where id = ? // for id [1]
select a, b, c, d from ... where id = ? // for id [2]
select a, b, c, d from ... where id = ? // for id [3]
. . .
select a, b, c, d from ... where id = ? // for id [1000]
Why is this a problem?
To do a thing takes a finite amount of time.
To do that thing a thousand times takes [at least] a thousand times as long.
The Program will be happy, just sitting, waiting, for the ORM library to give it back some data.
The Database will be happy, being asked to retrieve data based on a single value in a uniquely-indexed column.
The User will not be happy, waiting for all of these "little "queries to run, one after the other, to get the Data that they want and, quite likely, filling out Bug Reports while they're waiting.
Such Applications must be recoded to remove this behaviour.
This cannot be fixed at the database end, because the database is just doing what the code is asking it to do.