Wednesday, October 31, 2007

Database Ownern

Fick ett intressant fel när jag skulle välja egenskaper på en databas. En stor dialogruta sade att:

Property Owner is not available for Database '[DBNAMET]'. This property may not exist for this object, or may not be retrievable due to insufficient access rights. (Microsoft.SqlServer.Smo)

Efter lite antydningar från några artiklar på nätet så beror det på att OWNERN saknas på databasen. Efter att ha gjort en select på sysdatabases så såg jag att värdet var NULL. För att rätta till felet så är det bara att sätta en ny owner med SP_Changedbowner. Felet visar sig bara i 2005, inte i 2000 då man fortfarande kan välja egenskaper. Där emot blir kan man inte använda tex SP_Helpdb på databasen.

Kontentan utav detta är att se till att rätt user är owner på databasen efter installation. Det är lätt hänt att en utvecklare eller konsults konto blir borttaget och då få man dessa problem.

Wednesday, August 15, 2007

Partitions i SQL 2005

SQL 2005 innehåller en funktion som heter Partition vilket innebär att man helt enkelt dela ut en tabell eller index på flera filgrupper. Jag tänkte försöka förklara detta lite närmre här.

Låt oss säga att vi har en tabell som innehåller vanligt orderdata och en id kolumn. I detta exemplet så vill jag dela upp tabellen på id kolumnen. Order från 1 till 1000000 skall hamna i en fil grupp 1000001 till 2000000 skall hamna i filgrupp två osv och data över 3000000 i den sista filgruppen . Då börja vi med att skapa de fysiska databsfilerna och sedan själva filgrupperna. Vitsen med Partition är att sprida ut tabellen på flera ställen så att servern kan nyttja fler läsarmar i disksystemet. I detta fallet så skapade jag fyra st och lät dom heta DataFile1 osv.

Nu är det dags att skapa själva Partitionen (eller vad man nu skall kalla den på svenska).

Först funktionen:
CREATE PARTITION FUNCTION Function_tabellnamnet (INT)
AS RANGE RIGHT FOR VALUES (1000000, 2000000, 3000000)


Sedan Schemat:
CREATE PARTITION SCHEME Schema_tabellnamnet
AS PARTITION Function_tabellnamnet
TO (DataFile1, DataFile2, DataFile3, DataFile4)


Nu kan vi skapa själva tabellen:
CREATE TABLE Test (Id INT, OrderName VARCHAR(20), Date (datetime)) ON Schema_tabellnamnet (Id)

Nu är det bara att fylla tabellen med data och SQL kommer dela upp datat på flera filer och få möjlighet att läsa från fler ställen vilket förhoppningsvis kan öka prestandarden i systemet.
Vill man se hur datat är uppdelat mellan de olika partitionerna kan man göra det med följande kommando:
SELECT *
FROM sys.partitions
WHERE OBJECT_ID = OBJECT_ID('tabellnamn')

Eller:
select $partition.Function_tabellnamnet(id) as partitionNum, count(*)
from dbo.Test
group by $partition. Function_tabellnamnet (id)

Partition går även att använda på tex datum kolumner om det passa bättre. Kan vara bra om man tex vill lägga över gammalt data som inte används så frekvent till en annan disk. Finns en hel del möjligheter att pröva.

Monday, August 13, 2007

Medianvärde

Satt och klurade på att få ut medianvärdet från en pris column. Lyckades inte men efter lite googlande så hittade jag en fungerande sqlsats skriven utav Anjuna Moon i idg-s forum. För mig verka det fungera.

SELECT AVG(C1) AS Expr1
FROM (SELECT MAX(Price) C1
FROM (SELECT TOP 50 PERCENT Price
FROM [object]where type = 'värde'
ORDER BY Price) T1
UNION ALL
SELECT MIN(Price) C1
FROM (SELECT TOP 50 PERCENT Price
FROM [object] where type = 'värde'
ORDER BY Price DESC) T1) T3

Wednesday, June 13, 2007

Optimering utav SQL Server. Filgrupper

I en databasmiljö där man har mycket stora databaser finns en möjlighet att optimera SQLServern med Filgrupper. En databas består i grunden utav en Primary filgrupp där själva databasfilen ligger. Sen finns det en för transactionsloggen. Denna fil kan vi inte göra något med då loggfilen bara kan ha en filgrupp. Däremot kan databasfilen placeras i flera filgrupper. Varje filgrupp kan sedan ha flera filer under sig. Här kan man vinna en del performance genom att placera tabeller och index i olika filgrupper och sedan filerna på olika diskar. Nedan följer några tips att tänka på.

Tabeller som ofta JOINAS i en query skall inte ligga i samma filgrupp.

Om du har en tabell i databasen som du vet används mycket så överväg att placera den i en egen filgrupp på en egen disk. Då kan man dra nytta utav SQL-s förmåga att läsa datat sekventiellt vilket är mycket snabbare än vanlig läsning.

En tabell som används väldigt mycket kan dra nytta utav att placeras i flera filgrupper då datat kan läsas från fler ställen samtidigt. Kan man dessutom placera dessa filgruppers filer på egna diskar så skulle performancen bli ännu bättre.

På mycket stora databaser är backuper knappt hanterbara om man inte delar upp databasen i flera filgrupper.

Icke clustradeIndexen till en tabell kan läggas i en egen filgrupp.

Tempdb databasen som sköter alla sortering mm i SQL servern är lämplig att lägga i flera filgrupper för att då öka performancen.

Friday, May 18, 2007

Optimering utav SQL server. Index fragmentering

Hitta fragmentering i index

Vilka index skall vi leta fragmentering i? Liksom i den andra artikeln så bör vi titta efter index som används i tunga querys och som används ofta. Med hjälp utav SQL Profilern och den färdiga templaten SQLProfilerTSQL_Duration få vi fram en tracefil för vidare undersökning utav tabeller som kan vara lämpliga för en närmare analys.
I SQL 2000 används dbcc showcontig. I SQL 2005 finns det nya funktioner för att se denna information. Kör en SELECT * FROM sys.dm_db_index_physical_stats (DB_ID(N'AdventureWorks'), OBJECT_ID(), NULL, NULL , 'DETAILED');
I kollumnen avg_fragmentation_in_percent ser man fragmenteringen utav indexen, detta bör vara så nära noll som möjligt. Värdet avg_page_space_used_in_percent skall vara så nära 100 som möjligt eller så nära den fyllnadsgrad man valt på indexet. Med detta kommando få man ut massa information om indexet.

Ett exempel i sql 2000 kan se ut så här:

DBCC SHOWCONTIG scanning 'MIS_MIS_ART_SUP_HIST' table...
Table: 'MIS_MIS_ART_SUP_HIST' (1554104577); index ID: 1, database ID: 14
TABLE level scan performed.
- Pages Scanned................................: 8096
- Extents Scanned..............................: 1019
- Extent Switches..............................: 1018
- Avg. Pages per Extent........................: 7.9
- Scan Density [Best Count:Actual Count].......: 99.31% [1012:1019]
- Logical Scan Fragmentation ..................: 0.00%
- Extent Scan Fragmentation ...................: 0.10%
- Avg. Bytes Free per Page.....................: 1551.1
- Avg. Page Density (full).....................: 80.84%
DBCC execution completed. If DBCC printed error messages, contact your system administrator.

Här har vi då information om indexet på en tabell. För att det skall vara någon större idé att defragmentera så bör indexet generellt sett har mer än 1000 pages.

För att se om vi har en fragmetering utav indexet tittar vi främst på två värden. Avg. Page Density (full) som bör vara så nära den fyllnadsgrad som är valt på indexet. Är det skapat med 100% fyllnadsgrad så skall det liggar där omkring. I exeplet har vi just kört en dbcc dbreindex vilket optimerat indexet och fyllnadsgraden ligger nästan på 100%.

Logical Scan Fragmentation skall ligga så nära noll som möjligt. Går det över 10% börja det bli ett performance problem.

Med detta i tanken så är det lättare att avgöra om man skall defragmentera ett index eller ej. Att göra en sådan operation kan ta lång tid och mycket kraft från servern så behövs det inte så gör det ej.