SQL Script für die Erstellung von Best Practice SharePoint Datenbanken
erstellt in Allgemein, Samuel Zürcher von Samuel Zürcher
Wie in meinem letzten Post erläutert, macht es durchaus Sinn, sich im Bereich SharePoint auch über das Backend Gedanken zu machen. Ein Teil davon ist die Erstellung der Datenbanken. Eigentlich sollte es den Button „Add new Content Database“ in SharePoint gar nicht geben.
Warum? Hier sind die Gründe:
SharePoint erstellt eine neue Datenbank ab der Model und diese ist von Natur aus so konfiguriert:
- 2MB gross (oder besser gesagt klein)
- Ein einzelnes File in der Primary Filegroup
- Growth ist auf 1 MB Unlimited Growth
- Logfile ist 1MB gross
- Growth ist 10%
Nach dem Erstellen einer leeren SharePoint Datenbank ist diese 2o MB gross, das heisst, sie ist bereits 18x gewachsen. Durch das Wachstum einer DB wird sie fragmentiert und wie man weiss, ist alles was fragmentiert ist langsamer, da die Datenstücke nicht aneinander hängen, sondern verteilt sind. Diese Verteilung muss vom DB Management System aufgefangen werden. Dieser Reibungsverlust schlägt sich in der Performance nieder.
Wenn ich nun die DB Stats abfrage, bekomme ich den Fragmentierungslevel der neuen Datenbank mitgeteilt, ACHTUNG: Es handelt sich notabene um eine leere SharePoint Datenbank, die noch überhaupt keinen Content enthält. SELECT * FROM sys.dm_db_index_physical_stats (DB_ID(‚DB Name‘), Null, Null, Null, Null);
Ich erhalte hier 230 Rows, jede Row enthält den Hinweis auf einen Index. Meine Datenbank ist also schon sehr stark fragmentiert, obwohl sie leer ist. Da kann man sich vorstellen, dass dies an der Performance nagt.
Ein weiterer Punkt ist, dass allea auf einem Datenfile abgeht. Heute haben Prozessoren mehrere Kerne, und jeder hackt auf dem armen File rum. Viel besser ist es, wenn jeder Kern sich auf ein anderes File konzentrieren kann. Wenn eine DB in mehrere Files unterteilt ist, so wird abwechselnd auf die Files eingedroschen, was sich wiederum positiv auf die Performance auswirkt. Die Fausregel sagt, dass pro Prozessorkern 0.25 bis 0.5 Files angelegt werden sollten, mindestens aber 4. Bei mehr als 8 Files ist dann kein grosser Unterschied mehr spürbar. Beachten Sie folgendes:
- Berechnen Sie vorab, wie viel Content später mal in die DB rein soll
- Erstellen Sie die initiale DB Grösse entsprechend ein (wir sprechen von GB nicht von BYTES)
- Stellen Sie das Wachstum auf eine vernünftige Grösse ein
- Stellen Sie das LOG auch auf 1GB oder teilbar durch 8GB
Hier kommt der Script vorher noch im SQL Mgmt Studio unter „Query“ den „SQL CMD Mode“ aktivieren, alles was rot ist muss von euch noch customized werden (auch der User ganz am Ende, da kommt der Farm Admin rein:
— —————————————————————————————
— Disclaimer – Thoroughly test this script, execute at your own risk.
— —————————————————————————————
— set variables (Filesizes in MB)
:setvar DBName MyAdventDB
:setvar LoginitialMB 1024
:setvar LoggrowMB 1024
:setvar DatainitialMBperFile 341
:setvar DatagrowMBperFile 341
:setvar DataPath „C:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\DATA“
:setvar LogPath „C:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\DATA“
CREATE DATABASE [$(DBName)] ON PRIMARY
— no grow on Primary-File (its only for sys tables and Service Broker Queues)
( NAME = N’$(DBName)Data01′, FILENAME = N’$(DataPath)\$(DBName)Data01.mdf‘ , SIZE = 128MB , FILEGROWTH = 0),
— 0.25-1 file per cpu core (each with same initial and grow size)
( NAME = N’$(DBName)_Data02′, FILENAME = N’$(DataPath)\$(DBName)_Data02.ndf‘ , SIZE = $(DatainitialMBperFile)MB , FILEGROWTH = $(DatagrowMBperFile)MB ),
( NAME = N’$(DBName)_Data03′, FILENAME = N’$(DataPath)\$(DBName)_Data03.ndf‘ , SIZE = $(DatainitialMBperFile)MB , FILEGROWTH = $(DatagrowMBperFile)MB ),
( NAME = N’$(DBName)_Data04′, FILENAME = N’$(DataPath)\$(DBName)_Data04.ndf‘ , SIZE = $(DatainitialMBperFile)MB , FILEGROWTH = $(DatagrowMBperFile)MB ),
( NAME = N’$(DBName)_Data05′, FILENAME = N’$(DataPath)\$(DBName)_Data05.ndf‘ , SIZE = $(DatainitialMBperFile)MB , FILEGROWTH = $(DatagrowMBperFile)MB )
LOG ON
— place tlog on another diskarray, use best practice size for optimal vlf handling (1GB/8GB)
( NAME = N’$(DBName)_log‘, FILENAME = N’$(LogPath)\$(DBName)_log.ldf‘ , SIZE = $(LoginitialMB)MB , FILEGROWTH = $(LoggrowMB)MB )
— collation for database (default, unless its for moss –>KS_WS!)
COLLATE Latin1_General_CI_AS_KS_WS
GO
— 90=2005/100=2008
ALTER DATABASE [$(DBName)] SET COMPATIBILITY_LEVEL = 100
GO
ALTER DATABASE [$(DBName)] SET ANSI_NULL_DEFAULT OFF
GO
ALTER DATABASE [$(DBName)] SET ANSI_NULLS OFF
GO
— set ANSI_PADDING True, refer to BOL for more information, not default setting
ALTER DATABASE [$(DBName)] SET ANSI_PADDING ON
GO
ALTER DATABASE [$(DBName)] SET ANSI_WARNINGS OFF
GO
ALTER DATABASE [$(DBName)] SET ARITHABORT OFF
GO
ALTER DATABASE [$(DBName)] SET AUTO_CLOSE OFF
GO
ALTER DATABASE [$(DBName)] SET AUTO_CREATE_STATISTICS ON
GO
— never use AUTO_SHRINK on a production DB
ALTER DATABASE [$(DBName)] SET AUTO_SHRINK OFF
GO
ALTER DATABASE [$(DBName)] SET AUTO_UPDATE_STATISTICS ON
GO
ALTER DATABASE [$(DBName)] SET CURSOR_CLOSE_ON_COMMIT OFF
GO
ALTER DATABASE [$(DBName)] SET CURSOR_DEFAULT GLOBAL
GO
ALTER DATABASE [$(DBName)] SET CONCAT_NULL_YIELDS_NULL OFF
GO
ALTER DATABASE [$(DBName)] SET NUMERIC_ROUNDABORT OFF
GO
ALTER DATABASE [$(DBName)] SET QUOTED_IDENTIFIER OFF
GO
ALTER DATABASE [$(DBName)] SET RECURSIVE_TRIGGERS OFF
GO
ALTER DATABASE [$(DBName)] SET DISABLE_BROKER
GO
ALTER DATABASE [$(DBName)] SET AUTO_UPDATE_STATISTICS_ASYNC OFF
GO
ALTER DATABASE [$(DBName)] SET DATE_CORRELATION_OPTIMIZATION OFF
GO
ALTER DATABASE [$(DBName)] SET PARAMETERIZATION SIMPLE
GO
ALTER DATABASE [$(DBName)] SET READ_WRITE
GO
— use same recovery model for each db in an instance (exceptions in olap environments)
ALTER DATABASE [$(DBName)] SET RECOVERY FULL
GO
ALTER DATABASE [$(DBName)] SET MULTI_USER
GO
— change all dbs to checksum since 2005
ALTER DATABASE [$(DBName)] SET PAGE_VERIFY CHECKSUM
GO
— change db owner
USE [$(DBName)]
GO
EXEC dbo.sp_changedbowner @loginame = N‘domain\user‚, @map = false
GO
Am Ende noch mit Powershell an SharePoint anhängen und gut ist.
New-SPContentDatabase -Name <ContentDbName> -WebApplication <WebApplicationName>
So long, Samuel
16. Dezember 2011 um 09:10 Uhr
Vielen Dank für diesen Informativen und schön dargestelten Beitrag.
Eine Frage noch: sollte man den Log nicht auf eine Maximale Dateigrösse limitieren, so dass bei geringem Speicherplatz keine Gefahr besteht dass die Disk voll läuft?
18. Dezember 2011 um 11:53 Uhr
Hallo Reto, die Dateigrösse muss nicht limitiert werden, denn man sollte das Log so wie so nicht ins Unendliche wachsen lassen. Ein Logbackup in Abständen zwischen 15min. und 24 Stunden verhindert, dass das Logfile ins Unendliche wächst. Mit einem Backup des Logs gibst Du es frei zum Überschreiben. Gruss Samuel
16. Dezember 2011 um 19:16 Uhr
Wie ist das denn, wenn ich nun eine neue Web-Application einrichte. Dann lege ich also als erstes die DB an, und dan die Web-App und zeige auf die bereits vorhandene DB?
Und wenn SharePoint so sub-optimal seine Datenbanken anlegt, sollte ich dann nicht auch die anderen Datenbanken (MetaData, BDC, UPS, …) von SharePoint „manuell“ anlegen?
18. Dezember 2011 um 11:57 Uhr
Hallo Henning, das ist genau richtig. Um alles best practice zu installieren, sollte man alle Datenbanken per Script erstellen. Das generiert natürlich recht viel Aufwand, (vor Allem beim Search) daher muss man sich auch überlegen, in welchem Fall man so etwas macht. Ich schlage daher vor, bei Farmen > 1’000 User die DBs per Script zu erstellen. Dies ist ein grober richtwert. Hier findest Du die Anleitungen zum Erstellen aller DBs per script. http://technet.microsoft.com/de-de/library/cc262869.aspx Gruss Samuel
25. Dezember 2011 um 18:30 Uhr
Hallo Samuel,
vielen Dank für das How To.
Ich habe bei unserem SharePoint server leider genau die Standard Installation vorgenommen. Welche Möglichkeiten habe ich nun noch die vorhandene Datenbank zu optimieren bzw. deine How To umzusetzen. Ich bin leider kein DBA und habe nur basis-kentnisse bzgl. SQL Server.
Vielen Dank und euch allen fröhliche Weihnachten und einen guten Rutsch ins neue Jahr
Kai
17. Februar 2012 um 15:26 Uhr
Hallo Kai
Das machst Du, indem Du eine neue, saubere DB erstellst, und danach alle Site Collections mit dem Move-SPSite Befehl von Powershell in die neue DB verschiebst.
http://technet.microsoft.com/de-de/library/ff607915.aspx
Gruss Samuel