Jag vet inte vad som är bättre:svara på min fråga eller uppdatera den... så jag väljer att svara. Meddela mig om det är bättre att uppdatera
Vi får äntligen reda på problemet. Sedan version 3.1 har Rails lagt till förberedda uttalanden på enkel begäran som User.find(id). Version 4.0 lade förberedda uttalanden till förfrågningar om föreningar (har_många, tillhör_till, har_ett). Till exempel följande kod:
class User
has_many :adresses
end
user.addresses
generera begäran
SELECT "addresses".* FROM "addresses" WHERE "addresses"."user_id" = $1 [["user_id", 1]]
Problemet är att Rails bara lägger till förberedda satsvariabler för främmande nycklar (här user_id). Om du använder anpassad sql-förfrågan som
user.addresses.where("moved_at < ?", Time.now - 3.month)
det kommer inte att lägga till en variabel till de förberedda satserna för moved_at. Så det genererar förberedda uttalanden varje gång begäran anropas. Rails hanterar förberedda uttalanden med en pool på maxstorlek 1000.
Postgresql-förberedda uttalanden delas dock inte över anslutningar, så på en eller två timmar har varje anslutning 1000 förberedda satser. Vissa av dem är väldigt stora. Detta ledde till mycket hög minnesförbrukning på postgreqsl-servern.