sql >> Database teknologi >  >> RDS >> PostgreSQL

De fandens store genstande

Introduktion

PostgreSQL giver udviklere mulighed for at vælge mellem to mulige lagerfaciliteter til store binære data:Bytea og LargeObjects.

Store objekter har eksisteret i lang tid, og PostgreSQL har en smart måde at gemme store binære data på. Det gør det ved at opdele det i bidder af LOBLKSIZE (en fjerdedel af BLCKSZ). På den måde spilder tuplerne fra pg_largeobject ikke på toastbordet.

På den anden side bytea gemmer de binære data direkte i tuplen, hvilket kan føre til dårlig ydeevne afhængigt af hvordan dit skema ser ud.

Dette lyder godt, hvis du har en intelligent grænseflade til at håndtere manipulation af disse binære filer, især hvis opdatering kun ændrer en lille del af hele den binære fil.

Men normalt gider vi ikke skrive kode, der udnytter dette, og i stedet skriver vi igen af ​​hele binære data.

En af de ting, som jeg tror får folk til at adoptere store objekter, er de funktioner, der er tilgængelige til at importere og eksportere filer direkte fra databaseserveren til dets filsystem. Der er en ulempe ved dette:Hvis applikationen er på en anden server, skal du bruge mere kode for at flytte filen til det sted, hvor det er nødvendigt.

Et problem, du måske står over for

De sidste dage var jeg nødt til at undersøge en database, der blev brugt til at gemme information om brugersessioner fra et Java CAS-system. Jeg fandt ud af, at der var næsten 100 millioner store objekter i databasen, ikke særlig store.

Jeg gennemgik brugertabellerne og tjekkede de felter, der havde en oid felt, og derefter krydshenviser jeg værdierne i disse felter med pg_largeobject_metadata bord. Jeg fandt ud af, at 96 % af de store genstande var forældreløse. Det er store objekter, som ikke blev refereret af nogen tuple fra brugertabellerne.

Yderligere undersøgelser konkluderede, at Hibernate ikke tog sig af at rense de store objekter, det skabte, når de slettede eller opdaterede tuples med oid-felter. Så det genererede en stor mængde oppustethed, som ikke kunne ryddes op ved at støvsuge, men som skulle fjernes fra pg_largeobjects-tabellen manuelt.

I det særlige tilfælde med CAS-databasen tjente denne forespørgsel til at identificere de store objekter, der stadig er i brug:

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

Forespørgslen kan bruges til at udelukke fra listen over store objekter, hvilke der skal fjernes. Noget som dette:

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
)

Konklusion

Store objekter har deres problemer, ligesom andre typer data (især når du bruger typer til at gemme store binære data). Det er op til udviklerne og databaseadministratorerne at drage fordel af fordelene og afbøde ulemperne.

Vi gav en mulig forespørgsel om at udføre oprydningen, men der er også en fin udvidelse, som rydder op i de forældreløse store objekter med triggere:Large Object Manager

Nogle mennesker foretrækker måske at køre en udrensningsforespørgsel i stille timer i stedet for at udføre en trigger ved hver OPDATERING og SLET . På systemer med meget, meget lav OPDATERING og/eller SLET rate, en trigger over hver tabel, der har en oid felt, virker en mere elegant løsning. Og ethvert tab af ydeevne for at skulle udføre triggerfunktionen ville være overflødigt.

Under alle omstændigheder har store objekter stadig store fans, højst sandsynligt på grund af de interne funktioner til at importere og eksportere de binære data direkte til det lokale filsystem. Med bytea vil du normalt bruge mere hukommelse på applikationsniveauet. Det er en meget almindelig procedure at læse det binære felt fuldstændigt ind i en variabel og derefter behandle det.

Jeg vil måske skrive noget om at bruge bytea, som jeg brugte i en af ​​mine tidligere udviklinger i et fremtidigt blogindlæg.


  1. Få ugens startdato og ugens slutdato fra ugenummer

  2. Sådan får du adgang til et RowDataPacket-objekt

  3. Hvordan indlæses en XML-fil i en database ved hjælp af en SSIS-pakke?

  4. bestil efter newid() - hvordan virker det?