Overblog
Folge diesem Blog Administration + Create my blog
Blog von Olaf Helper

Wann ist +1 Monat?

30. September 2009 , Geschrieben von Olaf Helper Veröffentlicht in #T-SQL

In T-SQL des Microsoft SQL Servers gibt es die Funktion DATEADD, um auf ein Datum ein Intervall-Wert auf bzw. abzurechnen; sein es Tage, Wochen, Monate oder Ein Wert im Datumsbereich.

Einen Tag aufzurechnen, das ist klar und eindeutig: Aus Montag wird Dienstag und wie selbstverständlich wird aus dem 28.02.2009 der 01.03.2009 und nicht der 29.02, da es ja kein Schaltjahr ist.

Doch wie sieht es aus, wenn man einen Monat aufaddiert? Im Bankwesen ist er rechnerisch immer 30 Tage lang, im realen Leben variiert er aber. Wenn ich auf den 31.03. einen Monat rechne, kommt der 30.04. oder der 01.04. raus? Vom 30.04 ausgehend, erhalte ich den 30.05. oder den 31.05, weil es wie das Ausgangsdatum das Monatsende ist?

Bevor ich spekuliere, probiere ich es aus und das diesmal mit dem MS SQL 2008 mit der Möglichkeit der Multiple-Values.

 

T-SQL Statement:

 -- Wann ist +1 Monat? 
 SELECT * 
  ,DATEDIFF(dd, ThisDate, NextMonth) AS DayDiff 
 FROM  
  (SELECT ThisDate 
  ,DATEADD(mm, 1, ThisDate) AS NextMonth 
  FROM 
  (VALUES(CONVERT(date, '20081231')) 
  ,('20090131') ,('20090228') 
  ,('20090331') ,('20090430') 
  ,('20090531') ,('20090630') 
  ,('20090731')  
  ,('20090831') ,('20090930') 
  ,('20091031'), ('20091130') 
  ,('20091231')  
  ) AS Dates (ThisDate) 
  ) AS Dates 

 

Ergebnis: 

 ThisDate NextMonth DayDiff 
 ---------- ---------- ------- 
 2008-12-31 2009-01-31 31 
 2009-01-31 2009-02-28 28 
 2009-02-28 2009-03-28 28 
 2009-03-31 2009-04-30 30 
 2009-04-30 2009-05-30 30 
 2009-05-31 2009-06-30 30 
 2009-06-30 2009-07-30 30 
 2009-07-31 2009-08-31 31 
 2009-08-31 2009-09-30 30 
 2009-09-30 2009-10-30 30 
 2009-10-31 2009-11-30 30 
 2009-11-30 2009-12-30 30 
 2009-12-31 2010-01-31 31 

 

Das Ergebnis ist nicht gerade „deterministisch“: Grundsätzlich wird platt der Monat um eins hoch gezählt und wenn es ein ungültiges Datum ergibt, soweit tageweise zurück gerechnet, bis es gültig ist.

Ist halt so und sollte man immer im Hinterkopf behalten, wenn es um Auswertungen und ähnliches geht, um nicht falsche Zahlen zu erhalten.

Also: Um vom Monatsende auf das Monatsende des Folgemonats zu kommen, ist diese Methode ungeeignet. Besser man rechnet:

+ 1 Tag            (=Monatsanfang Folgemonat)

+ 1 Monat         (=Monatsanfang Übernächster Monat)

– 1 Tage           (=Monatsende Folgemonat)

 

=>

 

 SELECT DATEADD(DD, -1 
  ,DATEADD(MM, 1 
  ,DATEADD(DD, 1 
  ,'20090228' 
  ))) AS FolgeMonatsEnde 
Weiterlesen

Aktivität und Fortschritt einer Transaktion ermitteln

29. September 2009 , Geschrieben von Olaf Helper Veröffentlicht in #T-SQL

Lange Transaktion wie umfangreiche Updates in einem Dataware House lässt man meist per Job über Nacht laufen, da sitzt man nicht daneben und muss waren, bis es fertig ist; Hauptsache es ist bis zum nächsten morgen fehlerfrei durchgelaufen.

Wenn man aber gerade dabei ist, ein System auszubauen, muss man auch schon mal einen Langläufer anstarten und dann sitzt man da: Wie lange dauert es denn noch, wie weit ist die Transaktion bereits und macht er überhaupt noch was? Da wäre es schön, mal in den Microsoft SQL Server hineinschauen zu können.

Während einer solchen Wartezeit habe ich mal versucht, über die DMV (Dynamic Management Views) den Fortschritt einer Transaktion zu ermitteln; bei der DMV  sys.dm_tran_database_transactions bin ich fündig geworden. Die View liefert einem zu einer Transaktion die Anzahl der Transaktionsprotokoll-Einträge sowie die reservierte und verwendet Größe des Logs.

Das ist recht interessant und leicht verwirrend zu beobachten. Ich habe mal auf einem MS SQL Server 2005 mit SP 3 (9.00.4035.00) folgendes ausgeführt:

 

 UPDATE Tabelle 
 SET Feld1 = Feld1 
 WHERE id <= 500000 

 

Id ist eine Identity, es werden also 500k Datensätze upgedatet, wobei sich eigentlich nicht ändert, da das Feld der aktuelle Wert zugewiesen wird. Aber das kennt man schon, das trotzdem ein Update und damit eine Protokollierung im LOG erfolgt.

Das untenstehende zeigt das auch schon auf, man kann zusehen, wie die benötigt Größe & Anzahl steigt. Nun das interessante und zwar start ich das gleiche Update noch einmal, nur mit der WHERE Klausel

 WHERE id <= 600000 

Es werden also noch mal die gleichen 500k + weitere 100k an Datensätze upgedatet.

Beobachtet man mit dem Script diese Transaktion, werden zunächst nur 2 Einträge im LOG erzeugt, dann geschieht eine Zeit lang erst mal nichts weiter, bis dann doch noch 100k Sätze ins Log geschrieben werden; wohl die für die erstmal upgedateten.

Da scheint doch zumindest etwas optimiert zu sein.

 

Ich habe auch schon versucht, die „Restlaufzeit“ aufgrund der Daten zu schätzen, aber aufgrund des zuvor genannten Verhaltens ist das nicht so einfach. Vielleicht hat da jemand anderes noch eine Lösung zu.

 

Hier nun das T-SQL Script dazu, viel Vergnügen beim der Trans-Beobachtung:

 

 -- Selektion der Transaktionen eines Prozesses mit den  
 -- Daten des Transaktionsprotokolles wie Größe und 
 -- Anzahl Log-Sätze 
 DECLARE @spid as int; 
 SET @spid = 57; 
   
 SELECT PRO.spid, TDT.transaction_id, 
  CASE TDT.database_transaction_type 
  WHEN 1 THEN 'Read/Write' 
  WHEN 2 THEN 'ReadOnly' 
  WHEN 3 THEN 'System'  
  END AS TransType, 
  CASE TDT.database_transaction_type 
  WHEN 1 THEN 'Not initialized' 
  WHEN 3 THEN 'Initialized, no LOG generated' 
   WHEN 4 THEN 'LOG generated' 
  WHEN 5 THEN 'Preparing trans' 
  WHEN 10 THEN 'Committed' 
  WHEN 11 THEN 'Rolling back' 
  WHEN 12 THEN 'Committted, LOG generated, but not persisted'  
  END AS TransState, 
  PRO.waittime, PRO.waitresource, PRO.last_batch, 
  TDT.database_transaction_begin_time AS TransBegin, 
  TDT.database_transaction_log_record_count AS LogRecordCount, 
  TDT.database_transaction_log_bytes_used / 1024 AS LogKBUsed, 
   TDT.database_transaction_log_bytes_reserved / 1024 AS LogKBReserved, 
  CONVERT(decimal(8, 2),  
  DATEDIFF(ss, TDT.database_transaction_begin_time, GetDate()) / 60.0) AS DurationMin 
 FROM sys.dm_tran_database_transactions AS TDT 
  INNER JOIN sys.dm_tran_session_transactions AS TST 
  ON TDT.transaction_id = TST.transaction_id 
  INNER JOIN sys.sysprocesses AS PRO 
  ON TST.session_id = PRO.spid 
 WHERE PRO.spid = @spid 
  AND NOT TDT.database_transaction_begin_time IS NULL 
Weiterlesen

Aktuelle TechNet WebCasts und Seminare im Quartal 4 - 2009

27. September 2009 , Geschrieben von Olaf Helper Veröffentlicht in #Event

Im den kommenden 2 Monaten finden wieder, dem Titel nach zu urteilen interessante, TechNet WebCasts und TechNet Seminare zum Thema Microsoft SQL Server 2008 und 2008 R2 statt.

 

Webcasts

-       SQL Server 2008 R2 – Überblick über die CTP 2 (Level 200)

-       Projekt Gemini in SQL Server 2008 R2 – Teil 1: Die Clientseite

-       Reporting Services in SQL Server 2008 R2 – Maps und mehr (Level 200)

 

TechNet Seminare

-       SQL Server 2008 Clustering auf Windows Server 2008

-       SQL Server 2008 - Performance Tuning - Methoden, Werkzeuge und Best Practices

-       SQL Server 2008 aus der Sicht eines Softwareentwicklers

 

Preise für die Seminare habe ich bisher nicht gesehen, von daher gehe ich davon aus, dass sie (wie häufig) kostenfrei sind.

Die Seminare in Köln finden im Oktober statt, in Unterschleißheim im Dezember.

 

Die aktuellen Termine findet man am einfachsten über die Suche der Veranstaltungen.

Weiterlesen

Free eBook: SQL Server Tacklebox - Essential Tools and Scripts for the day-to-day DBA

27. September 2009 , Geschrieben von Olaf Helper Veröffentlicht in #Free eBooks

Die Firma Red-Gate hat ein weiteres eBook mit dem Titel „SQL Server Tacklebox - Essential Tools and Scripts for the day-to-day DBA” vom Autor Rodney Landrum veröffentlich, das es kostenlos zum Download gibt; eine Registrierung ist nicht nötig, man kommt ganz oben über „…If it does not, please click here zum Download.

Ich habe es bisher nur kurz überfolgen, es umfasst aber dem Titel entsprechend mit seinen 240 Seiten in leicht gekürzter Form alle Aspekte des DBA-Daseins.

Insbesondere die enthaltenen SQL Scripte sind sehr interessant, z.B. gleich das erste, um eine SQL Server Instanz nach den gewünschten Vorgaben zu konfigurieren.

Weiterlesen

„Create Or Alter“ für MS SQL Server

25. September 2009 , Geschrieben von Olaf Helper Veröffentlicht in #T-SQL

Bei Oracle und anderen DBMS gibt es die DDL Anweisung „Create Or Alter“ für Procedures, Functions und Views. Das ist praktisch, da man sich keine Gedanken machen muss, ob das Objekt schon vorhanden ist: Ist es vorhanden, wird es aktualisiert, sonst eben neu angelegt.

 

Im MS SQL Server gibt es so etwas leider nicht. Man behilft sich damit, dass man ein vorhandenes Objekt zunächst löscht (DROP) und dann wieder neu anlegt (CREATE). Das hat nur den großen Nachteil, dass alle vorhandenen Berechtigungen auch mit entfernt werden.

 

Dann gibt es noch zwei Möglichkeiten

-          Man pflegt die Berechtigungen im DROP/CREATE Script immer mit, was bei bei regelmäßigen Änderungen einen entsprechenden zusätzlichen Aufwand darstellt; und damit fehleranfällig. 

-          Man erstellt bei Design-Änderungen ein zusätzliches ALTER Script, nur wenn man eine neue Datenbank anlegt muss man daran denken, erst das CREATE und dann das ALTER Script auszuführen.

Beides nicht gerade komfortable und auch etwas fehlerträchtig.

 

Um „Create Or Alter“ nun doch noch abbilden zu können, habe ich mir folgendes überlegt

-          Wenn Objekt nicht vorhanden, dann mit „leerem“ Inhalt anlegen

-          Anschließend ein ALTER mit dem eigentlichen Design ausführen.

Dabei gibt es aber wieder ein kleines Problem, den die CREATE Anweisung muss die erste in einem Batch sein und somit kann man vorab nicht prüfen, ob das gewünschte Objekt bereits besteht. Aber das ist eben nur ein kleines Problem, dann legen über sp_executesqlmit einem SQL Script als Text an.

 

Beispiel:

 USE [AdventureWorks] 
 GO 
   
 IF OBJECT_ID('dbo.spTestSp', 'P ') IS NULL 
  EXEC sp_executesql N'CREATE PROCEDURE dbo.spTestSp AS SET NOCOUNT ON;' 
 GO 
   
 ALTER PROCEDURE dbo.spTestSp 
  @AddressID int 
 AS 
  SELECT * 
  FROM Person.Address 
  WHERE AddressID = @AddressID; 

 

Kein wirklicher Ersatz, aber mit T-SQL geht es halt nicht besser; zumindest nicht, das ich wüsste.

 

Weiterlesen

Microsoft SQL Server 2008-Onlinedokumentation (Juli 2009)

18. September 2009 , Geschrieben von Olaf Helper Veröffentlicht in #Download MSSQL

Eine aktualisierte Version der BOL (Books Online) für den Microsoft SQL Server 2008 Stand Juli 2009 (veröffentlicht 08.09.2009) gibt es im Download Center.
Die englischsprachige Version wurde zuvor bereits am 20.08.2009 publiziert.

Weiterlesen

IO und CPU Auslastung durch einzelne Prozesse

18. September 2009 , Geschrieben von Olaf Helper Veröffentlicht in #T-SQL

Wie man alle Prozesse mit deren ausgeführten SQL Statements auflistet, hatte ich schon mal ausgeführt.
Die nächste Frage, die sich daraus ergibt ist, wer von denen verursacht die meiste Last auf dem Server und zwingt ihn in die Knie?
Mit einem statischen SELECT kann man es nicht ermitteln, aber eine einfache Variante zur Ermittlung ist das folgende Vorgehen:
- Man erstellt zunächst einen Snapshot von den aktuellen Prozessen, bei dem auch die Werte für CPU und IO Auslastung je Prozess enthalten ist
- Dann wartet man etwas, umd den Prozessen auch Zeit zum arbeiten zu geben
- Nun vergleicht man den vorherigen Snapshot mit dem aktuellen Zustand der Prozesse

Zum Vergleichen muss man also den Snapshot mit sys.sysprocesses JOINen. Dabei nur über die SPID zu gehen, ist zu ungenau, den in der Wartezeit könnte der Prozesse beendet worden und die gleiche SPID an einen andere Verbindung vergeben worden sein. Deshalb JOIN ich zusätzlich noch über die SID (User GUID), ECID (Kontext ID) und Login-Zeit.

Ausgegeben werden nur Prozesse, wo entweder der Wert von Cpu oder Physical_Io sich geändert hat.

Was jeder noch für sich entscheiden muss, ist die Sortierung; ich habe hier die Sortierung nach der Cpu Last gewählt, was nicht in jedem Fall der wichtigste Faktor für eine Auslastung darstellt.
Hat man einen alten, schwachen Rechner, wird vielleicht die Cpu den Falschenhals darstellen; bei einer langsamen IO und deren Anbindung wohl eher der Wert. Leider kann man die beiden Werte nicht in Relation bringen (CPU = Zeit, IO = Anzahl), so dass man die Werte nicht sinnvoll kombinieren kann, um es als einen Wert zur Sortierung zu nutzen.

 -- Selektion, welcher Prozess am meisten CPU /IO Last verursacht 
 IF NOT OBJECT_ID('tempdb..#processes') IS NULL 
  DROP TABLE #processes  
 GO 
   
 -- Aktuellen Snapshot erstellen 
 SELECT spid, login_time, ecid, sid, 
  cpu, physical_io  
 INTO #processes  
 FROM sys.sysprocesses 
 GO 
   
 -- Kurz = 5 Sek warten, bis die Differenzwerte gebildet werden 
 WAITFOR DELAY '00:00:05' 
 GO 
   
 -- Selektion der Prozesse nach CPU/IO Last 
 SELECT ACT.cpu - PST.cpu AS CpuDiff 
  ,ACT.physical_io - PST.physical_io AS IoDiff 
  ,ACT.spid 
  ,DB.name AS DataBaseName 
  ,ACT.hostname 
  ,ACT.program_name 
  ,ACT.loginame 
  ,ACT.cmd 
  ,EST.text AS SQLStatement 
 FROM sys.sysprocesses AS ACT 
  INNER JOIN #processes AS PST 
  ON ACT.spid = PST.spid 
  AND ACT.ecid = PST.ecid 
  AND ACT.sid = PST.sid 
  AND ACT.login_time = PST.login_time 
  INNER JOIN sys.databases AS DB 
  ON ACT.dbid = DB.database_id 
  CROSS APPLY sys.dm_exec_sql_text(ACT.sql_handle) AS EST 
 WHERE (ACT.cpu - PST.cpu) > 0 
  OR (ACT.physical_io - PST.physical_io) > 0 
 ORDER BY CpuDiff DESC, ACT.cpu DESC 
  ,IoDiff DESC, ACT.physical_io DESC 
 GO 
 DROP TABLE #processes  
 GO 

 

Weiterlesen

Designing SQL Server 2005 Analysis Services Cubes for Excel 2007 PivotTables

11. September 2009 , Geschrieben von Olaf Helper Veröffentlicht in #OLAP

Eine, wie ich finde, wirklich gute Dokumentation zum Thema Design-Tipps von Cubes gibt es im zum Dowload als Word Doukument im Download-Center von Microsoft.
In der Best Practice Tipps wird aufgeführt, mit welchen Ordnungselementen und anderen Eigenschaften man im SQL Server Analysis Services (SSAS) eine OLAP Cube mit deren Dimension und Attribute so gestaltet kann, das dem Endanwender ein einfaches und übersichtliches Arbeiten ermöglicht wird.

Weiterlesen

Microsoft SQL Server 2008-Onlinedokumentation (Juli 2009)

11. September 2009 , Geschrieben von Olaf Helper Veröffentlicht in #Download MSSQL

Microsoft hat eine Aktualisierung von der BOL (Books Online) zum MS SQL Server 2008 eröffentlich, sie ist verfügbar in den Sprache
- deutsch (141 MB)
- englisch (144 MB; ob da mehr drin steht???)

Weiterlesen