Před časem jsem řešil problém, kdy databáze služby Import uživatelských profilů měla velikost přes 21GB. To je na profily cca 150 členů domény poměrně dost. Začal jsem proto pátrat po tom čím by to mohlo být způsobeno a jak to vyřešit.
Prozkoumáním databáze (typicky ve svém jméně obsahuje UserProfile, její přesné jméno naleznete v konfiguraci služby Import uživatelských profilů) jsem zjistil, že drtivá většina dat se nachází v tabulce InstanceData. Tato tabulka slouží v průběhu importu. Problém je v tom, že se z ní nemažou nepotřebné záznamy z již proběhlých importů. Dokonce mezi uloženými procedurami můžete najít jednu, která se nachází ve schématu FIM a jmenuje se [TruncateInstanceData]. Je to dáno tím, že oproti předchozí verzi SP 2007, kde byl import omezen na Active Directory a byl řešen proprietárně, v SP 2010 je import řešen pomocí tzv. FIMu (Forefront Identity Manager). To je obecný nástroj pro distribuci informací z uživatelských profilů mezi různými systémy. Díky tomu může být zdrojem uživatelských informací i jiný informační systém, než jen Active Directory. Bohužel při implementaci FIMu (resp. jeho omezené části) do SharePointu došlo někde k chybě a zmíněná procedura se nevolá tak, jak by měla a nedochází k mazání již nepotřebných informací. Databáze proto roste a roste...
Řešením, které se nabízí, je ruční spuštění této procedury a její pravidelné spouštění. Protože ale procedura obsahuje jediný delete příkaz, může se vám stát, že po několika hodinách jejího běhu zjistíte, že skončila chybou a nedošlo ke zmenšení tabulky ani databáze. Je to proto, že elementární operace (např. DELETE) běží jako transakce. V průběhu transakce se vytváří log toho co se stalo, aby bylo možné případně transakci rollbackovat. Proto mazání velkého množství dat najednou vede k velkým nárokům na velikost databázového logu. Proto vám doporučuji následující:
- Změnte recovery schéma z Full na Simple. Tím docílíte toho, že po dokončení transakce se jí vygenerovaná část logu smaže.
- DELETE příkaz z procedury si vykopírute bokem a spouštějte několikrát za sebou s vhodnou podmínkou tak, aby množství mazaných záznamů nebylo příliš velké.
- Nakonec proveďte shrink databáze. Tím se uvolní prázdné místo po smazaných záznamech a dojde ke skutečnému zmenšení databázových souborů. To uděláte např. pomocí kontextového menu databáze v MS SQL Management Studiu. Zde najdete položku Tasks -> Shrink
- Přepněte recovery schéma databáze na původní hodnotu.
Protože jsem na webu narazil na informaci, že v některých databázích zmiňovaná procedura vůbec není, přikládám její podobu tak, jak jsem ji našel v mnou zkoumané databázi:
/****** Object: StoredProcedure [FIM].[TruncateInstanceData] */
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [FIM].[TruncateInstanceData]
AS
BEGIN
--************************************************************
--* *
--* Copyright (C) Microsoft. All rights reserved. *
--* *
--************************************************************
SET NOCOUNT ON;
DECLARE @truncationTime datetime;
SET @truncationTime = DATEADD(day, -1, GETUTCDATE());
DELETE FROM [dbo].[InstanceData]
WHERE ([created] < @truncationTime)
END
GO