Umbraco pre v4 database oprydning

Jeg havde for nylig et site der kørte på Umbraco og som kørte enormt langsomt og fungerede egentlig ikke rigtigt. Jeg undrede mig en del over det, for indholdsmæssigt var det ikke et tungt site (kun få sider - mindre end 100), men et site der havde været i drift i en længere periode. Jeg besluttede mig for at finde ud af hvorfor det ikke fungerede. Her er hvad jeg fandt frem til...

Symptomerne

Sitet kørte som nævnt ikke rigtigt. Helt konkret var det enormt langsomt til at indlæse træstrukturen og det var et held, hvis man fik lov til at oprette nye dokumenter.

Det er klart, at man ikke kan forvente hvad som helst af en 10+ år gammel undskyldning for en server, men jeg havde da også andre Umbraco-sites på denne server, som slet ikke havde problemer med at køre, så jeg mente jo nok dette ikke burde være et problem. Også det faktum, at der var tale om et Umbraco v3.0.6 kunne vække en vis bekymring, men igen, så var der også andre sites i denne version, på samme server, som kørte tilfredsstillende.

Opdagelsen

Efter af have kigget lidt rundt i Umbraco-admin, uden dog at kunne finde noget, der virkede himmelråbende tåbeligt konfigureret, bedrog jeg mig ud i stifinderen, for at se om der kunne være noget der. Første stop web.config, men også her så tingene tilforladelige ud, så heller ikke der synes jeg, der var noget at hente.

Efter lidt stikken og justeren, fandt jeg frem til databasefilerne (data og log) for sitet og til min store overraskelse opdagede jeg, at data-filen fyldte 2.3+ Gb! Det var vist ikke nødvendigt for sådan et lille site, så noget måtte være galt, men hvad!?

Undersøgelsen

Gad vide hvordan sådan en Umbraco database er bygget op? En hel masse tabeller præfikset med cms og umbraco og lidt svær at gennemskue, hvis man ikke har arbejdet indgående med sådan en før (hvilket jeg ikke havde), så Google måtte kunne hjælpe...(?)

Først og fremmest måtte jeg have et overblik over hvormeget data der var i hvilke tabeller. Til dette formål fandt jeg flg. SQL-script, som, om en given database, kunne fortælle mig, hvormange rækker der er i hver tabel, hvormeget tabellens indhold fylder i Kb m.m.

SELECT 
    t.NAME AS TableName,
    s.Name AS SchemaName,
    p.rows AS RowCounts,
    SUM(a.total_pages) * 8 AS TotalSpaceKB, 
    SUM(a.used_pages) * 8 AS UsedSpaceKB, 
    (SUM(a.total_pages) - SUM(a.used_pages)) * 8 AS UnusedSpaceKB
FROM 
    sys.tables t
INNER JOIN      
    sys.indexes i ON t.OBJECT_ID = i.object_id
INNER JOIN 
    sys.partitions p ON i.object_id = p.OBJECT_ID 
                    AND i.index_id = p.index_id
INNER JOIN 
    sys.allocation_units a ON p.partition_id = a.container_id
LEFT OUTER JOIN 
    sys.schemas s ON t.schema_id = s.schema_id
WHERE 
    t.NAME NOT LIKE 'dt%' 
    AND t.is_ms_shipped = 0
    AND i.OBJECT_ID > 255 
GROUP BY 
    t.Name, s.Name, p.Rows
ORDER BY 
    t.Name

Efter at have kørt dette script i SSMS, fik jeg en fornemmelse af, at problemet havde med versionering af dokumenterne at gøre. De tabeller som indeholdte markant mere data end forventet, var cmsContentVersion, cmsDocument, cmsPropertyData og umbracoLog. Uden at ville (og kunne) gå i yderligere detaljer om, hvad disse tabeller konkret bruges til, indikerer det i det mindste, at det har noget med versionering at gøre. Spørgsmålet er bare, hvorfor? Der er ikke specielt meget aktivitet i relation til vedligeholdelse af indhold på sitet, så hvorfor er der oprettet så mange rækker i disse tabeller (der var over 500.000 i cmsDocument og cmsContentVersion og over 3.500.000 i cmsPropertyData, ligesom der også var omkring 1.200.000 i umbracoLog...!

Et kig i umbracoLog afslører en periodisk publisering af to specifikke dokumenter, som resulterer i 4 nye rækker i umbracoLog, samt nye 2 eller flere rækker i hver af de andre tabeller, hver gang. Hver gang vil sige, hvert minut 24/7/365 - det bliver til en del rækker med tiden... :-)

Det var naturligvis ikke en optimal situation, så der måtte da være en løsning på dette. Hvorfor blev disse to dokumenter (indholdssider på linje med en masse andre på sitet) publiseret med 1 minuts intervaller og mere vigtigt, hvordan fik jeg det så stoppet!?

"Løsningen"

Derfor måtte jeg finde ud af, hvordan jeg kunne løse dette. Google er min ven(!), men selv venner har sine begrænsninger, så det lykkedes den ikke at fremskaffe en løsning. Den eneste tilnærmelsesvis overkommelige løsning var, at opgradere til en nyere version, hvor dette ikke længere var et problem. Det lader nemlig til at være et bug i nogle versioner (herunder v3.0.6, som dette site jo kører), som bevirker, at der publiseres på denne måde.

Jeg skal erkende, at jeg heller ikke har søgt efter en løsning meget mere end en times tid, da sitet skulle pilles ned indenfor en overskuelig tidshorisont, så det kan være der rent faktisk kan køres et workaround, som løser dette, men jeg er som sagt ikke faldet over det.

Det jeg så gør i stedet, er symptombehandling (when all else fails...). Det indbefatter en periodisk udførsel af et SQL script, som sletter alle versioner op til en bestemt dato (i nedenfor viste script, er det til dagen før den dato hvorpå scriptet udføres) og som ikke er den aktive version. Dette script ser således ud.

DECLARE @createdDate Datetime
SET @createdDate = DateAdd(day, -1, getdate())

DELETE FROM cmsPropertyData WHERE
    versionId NOT IN (
              SELECT versionId 
              FROM cmsDocument 
              WHERE updateDate > @createdDate 
                 OR published = 1 
                 OR newest = 1) AND
    contentNodeId IN (SELECT DISTINCT nodeID FROM cmsDocument)

DELETE FROM cmsContentVersion WHERE
    versionId NOT IN (
              SELECT versionId 
              FROM cmsDocument 
              WHERE updateDate > @createdDate 
                 OR published = 1 
                 OR newest = 1) AND
    ContentId  IN (SELECT DISTINCT nodeID FROM cmsDocument)

DELETE FROM cmsDocument WHERE
    versionId NOT IN (
              SELECT versionId 
              FROM cmsDocument 
              WHERE updateDate > @createdDate 
                 OR published = 1 
                 OR newest = 1) AND
    nodeId IN (SELECT DISTINCT nodeID FROM cmsDocument)

Dette script, når det bliver gemt som en fil og placeret på serveren, kan så, med jævne mellemrum, aktiveres, som en baggrundsopgave på serveren, hvor scriptet kaldes med sqlcmd.

sqlcmd -S myServer\instanceName -i C:\sqlscripts\umbracoCleanup.sql

Konklusion

Nu har jeg i det mindste fået lidt styr på databasevæksten på mit site, selvom jeg ikke synes dette er den optimale løsning (langt fra - det bedste ville jo være, at publiseringen ikke gik i selvsving!). Nogle gange er vi bare nød til, at nøjes med mindre, så vi kan komme videre med det der er rigtig fedt! :-)

 

1 Comment on “Umbraco pre v4 database oprydning”

  1. Gravatar of custom essay writing service

    I enjoy reading through your article post, I wanted to write a little comment to support you and wish you a good continuation.

Comment