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! :-)