sql >> Database >  >> RDS >> PostgreSQL

Die verdomd grote objecten

Inleiding

PostgreSQL geeft ontwikkelaars de kans om te kiezen tussen twee mogelijke opslagfaciliteiten voor grote binaire gegevens:Bytea en LargeObjects.

Grote objecten bestaan ​​al heel lang en PostgreSQL heeft een slimme manier om grote binaire gegevens op te slaan. Het doet dit door het op te splitsen in brokken LOBLKSIZE (een vierde van BLCKSZ). Op die manier morsen de tuples van pg_largeobject niet op de toasttafel.

Aan de andere kant bytea slaat de binaire gegevens rechtstreeks op in de tuple, wat kan leiden tot slechte prestaties, afhankelijk van hoe uw schema eruitziet.

Dit klinkt geweldig als je een intelligente interface hebt voor het omgaan met de manipulatie van deze binaire bestanden, vooral als update slechts een klein deel van het hele binaire bestand wijzigt.

Maar normaal gesproken doen we niet de moeite om code te schrijven die hiervan profiteert, en in plaats daarvan schrijven we opnieuw van de hele binaire gegevens.

Een van de dingen waarvan ik denk dat mensen grote objecten adopteren, zijn de functies die beschikbaar zijn voor het rechtstreeks importeren en exporteren van bestanden van de databaseserver naar het bestandssysteem. Hier zit een nadeel aan:als de applicatie op een andere server staat, heb je meer code nodig om het bestand te verplaatsen naar de locatie waar het nodig is.

Een probleem waarmee u mogelijk te maken kunt krijgen

De afgelopen dagen moest ik een database onderzoeken die werd gebruikt om informatie van gebruikerssessies van een Java CAS-systeem op te slaan. Ik ontdekte dat er bijna 100 miljoen grote objecten in de database waren, niet erg grote.

Ik heb de gebruikerstabellen doorgenomen en de velden gecontroleerd met een oid veld, en dan verwijs ik naar de waarden in die velden met de pg_largeobject_metadata tafel. Ik ontdekte dat 96% van die grote objecten wees waren. Dat zijn grote objecten waarnaar door geen enkele tuple uit de gebruikerstabellen wordt verwezen.

Nader onderzoek concludeerde dat Hibernate niet zorgde voor het opschonen van de grote objecten die het maakte bij het verwijderen of bijwerken van tuples met oid-velden. Het genereerde dus een grote hoeveelheid zwelling die niet kon worden opgeruimd door te stofzuigen, maar die handmatig uit de pg_largeobjects-tabel moest worden verwijderd.

In het specifieke geval van de CAS-database diende deze zoekopdracht om de grote objecten te identificeren die nog in gebruik zijn:

SELECT unnest(array[expiration_policy,
                    authentication,
                    services_granted_access_to])
       FROM public.ticketgrantingticket
UNION
SELECT unnest(array[expiration_policy, 
                    service])
       FROM public.serviceticket

De query kan worden gebruikt om uit de lijst met grote objecten uit te sluiten welke moeten worden verwijderd. Zoiets als dit:

SELECT lo_unlink(pg_largeobject_metadata.oid)
       FROM pg_largeobject_metadata
       WHERE pg_largeobject_metadata.oid NOT IN (
             SELECT unnest(array[expiration_policy,
                                 authentication,
                                 services_granted_access_to])
             FROM public.ticketgrantingticket
             UNION
             SELECT unnest(array[expiration_policy, 
                                 service])
             FROM public.serviceticket
)

Conclusie

Grote objecten hebben hun problemen, net als andere soorten gegevens (vooral bij het gebruik van typen om grote binaire gegevens op te slaan). Het is aan de ontwikkelaars en databasebeheerders om te profiteren van de voordelen en de nadelen te beperken.

We hebben een mogelijke query gegeven om de opschoning uit te voeren, maar er is ook een mooie extensie die de verweesde grote objecten opruimt met triggers:Large Object Manager

Sommige mensen geven er misschien de voorkeur aan een opschoonquery uit te voeren tijdens stille uren in plaats van elke UPDATE een trigger uit te voeren en VERWIJDEREN . Op systemen met zeer, zeer lage UPDATE en/of VERWIJDEREN rate, een trigger voor elke tafel met een oid veld, lijkt een elegantere oplossing. En elk prestatieverlies voor het moeten uitvoeren van de triggerfunctie zou overbodig zijn.

In ieder geval hebben grote objecten nog steeds grote fans, hoogstwaarschijnlijk vanwege de interne functies die worden geboden om de binaire gegevens rechtstreeks naar het lokale bestandssysteem te importeren en exporteren. Met bytea zou je normaal gesproken meer geheugen gebruiken op de applicatielaag. Het is een veelgebruikte procedure om het binaire veld volledig in een variabele in te lezen en het vervolgens te verwerken.

Ik zou in een toekomstige blogpost iets kunnen schrijven over het gebruik van bytea die ik in een van mijn eerdere ontwikkelingen heb gebruikt.


  1. Stuurprogramma JDBC PostgreSQL met Android

  2. Hybride OLTP/Analytics-databaseworkloads:MySQL-gegevens repliceren naar ClickHouse

  3. Testgegevens genereren in SQL Server

  4. MySQL datumnotatie spiekbriefje