sql >> Databáze >  >> RDS >> PostgreSQL

Ty zatraceně velké předměty

Úvod

PostgreSQL dává vývojářům možnost vybrat si mezi dvěma možnými úložnými zařízeními pro velká binární data:Bytea a LargeObjects.

Velké objekty existují již dlouhou dobu a PostgreSQL má chytrý způsob ukládání velkých binárních dat. Dělá to tak, že je rozděluje na části LOBLKSIZE (čtvrtina BLCKSZ). Tímto způsobem se n-tice z pg_largeobject nevysypou na toustový stůl.

Na druhou stranu bytea ukládá binární data přímo do n-tice, což může vést ke špatnému výkonu v závislosti na tom, jak vaše schéma vypadá.

To zní skvěle, pokud máte inteligentní rozhraní pro manipulaci s těmito binárními soubory, zvláště pokud aktualizace upraví pouze malou část celého binárního souboru.

Ale normálně se neobtěžujeme psát kód, který toho využívá, a místo toho zapisujeme znovu celá binární data.

Jednou z věcí, které podle mého názoru přimějí lidi přijmout velké objekty, jsou funkce dostupné pro import a export souborů přímo z databázového serveru do jeho souborového systému. Má to nevýhodu:pokud je aplikace na jiném serveru, budete potřebovat další kód k přesunutí souboru na místo, kde je potřeba.

Problém, se kterým se můžete setkat

V minulých dnech jsem musel prozkoumat databázi používanou k ukládání informací o uživatelských relacích ze systému Java CAS. Zjistil jsem, že v databázi bylo téměř 100 milionů velkých objektů, ne příliš velkých.

Prošel jsem uživatelské tabulky a zkontroloval jsem pole, která měla oid a poté křížovým odkazem na hodnoty v těchto polích pomocí pg_largeobject_metadata stůl. Zjistil jsem, že 96 % těchto velkých objektů je osiřelých. To jsou velké objekty, na které se neodkazovala žádná n-tice z uživatelských tabulek.

Další vyšetřování dospělo k závěru, že Hibernate se nestaral o vyčištění velkých objektů, které vytvořil při mazání nebo aktualizaci n-tic s oidovými poli. Takže to generovalo velké množství nadýmání, které nebylo možné vyčistit vysáváním, ale muselo být odstraněno z tabulky pg_largeobjects ručně.

V konkrétním případě databáze CAS sloužil tento dotaz k identifikaci dosud používaných velkých objektů:

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

Dotaz lze použít k vyloučení ze seznamu velkých objektů, které z nich odstranit. Něco jako toto:

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
)

Závěr

Velké objekty mají své problémy, stejně jako jiné typy dat (zejména při použití typů k ukládání velkých binárních dat). Je na vývojářích a správcích databází, aby využili výhod a zmírnili nevýhody.

Dali jsme možný dotaz k provedení vyčištění, ale existuje také pěkné rozšíření, které vyčistí osiřelé velké objekty pomocí spouštěčů:Správce velkých objektů

Někteří lidé mohou upřednostňovat spouštění dotazu pro čištění během klidových hodin namísto spouštění spouštěče při každé AKTUALIZACI a SMAZAT . Na systémech s velmi, velmi nízkou hodnotou UPDATE a/nebo DELETE sazba, spouštěč nad každou tabulkou, která má oid pole, se jeví jako elegantnější řešení. A jakákoli ztráta výkonu kvůli nutnosti provést spouštěcí funkci by byla zbytečná.

V každém případě mají velké objekty stále velké fanoušky, s největší pravděpodobností kvůli interním funkcím pro import a export binárních dat přímo do místního souborového systému. S bytea byste normálně spotřebovali více paměti na aplikační vrstvě. Je to velmi běžný postup, jak celé binární pole načíst do proměnné a poté je zpracovat.

Možná bych mohl napsat něco o použití bytea, který jsem použil v jednom ze svých minulých vývojů, v budoucím příspěvku na blogu.


  1. ORA-01658:nelze vytvořit INITIAL rozsah pro segment v tabulkovém prostoru TS_DATA

  2. Poškozený soubor exportu SQL Server BCP?

  3. MySQL CHAR() vs T-SQL CHAR():Jaký je rozdíl?

  4. #1055 - Výraz seznamu SELECT není v klauzuli GROUP BY a obsahuje neagregovaný sloupec, což není kompatibilní s sql_mode=only_full_group_by