Primo e Ultimo Giorno del Mese #SQL2012

Oggi avevo bisogno di calcolarmi primo ed ultimo giorno del mese di certa data, T-SQL non offre nulla di preconfezionato (o almeno io non l’ho trovato..) così ho deciso di scrivere due funzioncine:

Alter function UDF_GetFirstDateOfMonth(@MyDate as Datetime)
RETURNS Datetime
AS
BEGIN
 DECLARE @returnDate datetime
 SELECT @returnDate = CAST(dateadd(dd,-day(@MyDate)+1,@MyDate) as date)
 RETURN @returnDate
END

GO

/*
select log_live.dbo.UDF_GetFirstDateOfMonth(getdate())
*/



Alter function UDF_GetLastDateOfMonth(@Mydate as Datetime)
RETURNS Datetime
AS
BEGIN
 DECLARE @returnDate datetime
 SELECT @returnDate = CAST(dateadd(dd,-day(@MyDate),dateadd(mm,+1,@MyDate)) as date)
 RETURN @returnDate
END

GO

/*
select log_live.dbo.UDF_GetLastDateOfMonth(getdate())
*/
Annunci
Pubblicato in sql, Utilità | Lascia un commento

Indici SQL reorganize o reindex?

Sin da quando ho cominciato a ravanare in SQL le prime volte mi sono fatto un pò di domande sulla manutenzione degli indici.
Nel mio caso, forse una delle prime cose che ho imparato su MSSQL è che i dati vengono scritti fisicamente sul disco seguendo l’indice clustered. Teoricamente infatti, l’indice clustered di una tabella andrebbe creato pensando per bene a come i dati vengono scritti nel DB, certo, non è l’unica considerazione da fare, ma di sicuro è la prima domanda da porsi..
prima domanda.. che succede se ho creato l’indice clustered sulla chiave primaria e un bel giorno mi rendo conto che i dati entrano nella tabella in tutt’altro ordine? e agli altri indici che succede? questi ultimi poi, al 99% sono stati pensati per velocizzare interrogazioni delle mie amate tabelle senza tenere minimamente conto di come il dato viene scritto sul disco..

Innanzitutto vediamo come verificare quanto i miei indici sono frammentati, il technet mette a disposizione una query che funziona su varie versioni di SQL (se non sbaglio dalla 2005 in poi) che, in caso il link si rompa copio e incollo qui sotto:


SELECT a.index_id, name, avg_fragmentation_in_percent
FROM sys.dm_db_index_physical_stats (DB_ID(N'AdventureWorks2012'), OBJECT_ID(N'HumanResources.Employee'), NULL, NULL, NULL) AS a
JOIN sys.indexes AS b
ON a.object_id = b.object_id
AND a.index_id = b.index_id;

lanciandola (se avete dei tabelloni ci vorrà un pò di tempo la prima volta) avrete un risultato abbastanza interessante.


index_id name avg_fragmentation_in_percent
----------- ------------- --------------------------
1 PK_My_Table 28,8063656865314
2 Index01_MyTable 29,7625459873218
3 Index03_MyTable 0

(3 row(s) affected)

cosa capire da quanto qui sopra?

1) chiave primaria e indice Index01 sono piuttosto frammentati, si parla di circa il 30% per tutte e due
2) Index03 è frammentato Zero

Cosa Fare?

Secondo l’articolo del Technet che ho linkato, se la frammentazione si mantiene al di sotto del 30% è ottimale effettuare una reorganize degli indici, nel caso invece siamo fuori da questo parametro è molto più conveniente effettuare una rebuild.

che differenza c’è fra le due opzioni?

la Rebuild dell’indice effettua un DROP dell’indice ed una sua rigenerazione totale, è un’operazione che mette off-line la tabella, quindi se effettuata con operazioni schedulate è necessario tenere in cosiderazione che dall’inizio delle operazioni fino al loro termine la tabella sarà offline.

la Reorganize effettua una semplice riorganizzazione della tabella, la mantiene on-line, continuando a garantire la sua operatività anche durante le operazioni di manutenzione. l’accesso sarà un pò rallentato e, avrò necessità di un pò di spazio disco in quanto, per effettuare la rebuild, l’engine dovrà appoggiare da qualche parte il pezzetto di indice che sta riorganizzando, prima di scriverlo nel suo spazio definitivo.

quindi io che sono proprio al limite del valore indicato da Microsoft che faccio?

la tentazione per molti sarebbe quella di fare una reorganize e non pensarci più… La macchina lavora da sola, per quanto tempo ci possa mettere i miei utenti saranno solo rallentati ma potranno continuare a lavorare e tanti ecc ecc

ma è tutto oro quel che luccica?

non sempre..

anche in questo caso bisogna fare un pò di considerazioni considerando 3 parametri:

1) Dimensioni della tabella
2) potenza dell’hardware su cui gira la mia istanza
3) volume degli accessi alla tabella

mi spiego meglio, i 3 parametri di cui sopra (e qualche test) saranno fondamentali per capire quale opzione scegliere, due casi:

Ho una tabella di qualche milione di righe, su un hardware un pò datato, gli accessi non sono tanti, parliamo di una frammentazione di circa 15/20%.
a guardare i parametri e seguire le indicazioni di casa Microsoft verrebbe da scegliere la reorganize. Personalmente, una Rebuild la prenderei in considerazione, approfittando del basso numero di accessi e magari con la complicità di un fine settimana.

altro caso, ho una tabella di qualche migliaio di righe, frammentazione 50/60% diverse centinaia di accessi al secondo. In questo caso l’hardware è un parametro fondamentale, se parliamo di una macchina di ultimissima generazione, magari con la ram sufficente a contenere tutti i DB Dell’istanza, forse una rebuild si può prendere in considerazione. Se al contrario invece siamo in una situazione in cui l’hardware non è potentissimo, se lo spazio disco lo consenteè forse il caso di prendere in considerazione una Reorganize, in fondo la tabella è di dimensioni limitate e l’alto numero di accessi contemporanei forse pregiudica l’operatività di un numero di utenti troppo alto per giustificarne uno stop, anche di breve durata.

come possiamo fare dei test?

semplice.. mantenendo, o creando, un ambiente di test adeguatamente misurato.
Nell’azienda dove lavoro gira un ambiente di pre-produzione, dimensionato in modo da essere circa il 30% dell’ambiente di produzione. Questo ci permette di effettuare dei test consistenti che ci diano, facendo i dovuti conti, un’idea del lavoro che dovremo affrontare quando metteremo le mani nell’ambiente di produzione.
dove questo non sia possibile si può effettuare utilizzando un backup, su una macchina “muletto”.

In definitiva

laddove non ci siano situazioni chiare, la necessità è SEMPRE fare dei test prima, sopratutto tenendo a mente una cosa.. quanto ci metto a ripristinare i backup nel caso qualcosa non vada a buon fine?…

Pubblicato in Dove Stiamo Andando? | Lascia un commento

2012 in review

I folletti delle statistiche di WordPress.com hanno preparato un rapporto annuale 2012 per questo blog.

Ecco un estratto:

600 people reached the top of Mt. Everest in 2012. This blog got about 1.900 views in 2012. If every person who reached the top of Mt. Everest viewed this blog, it would have taken 3 years to get that many views.

Clicca qui per vedere il rapporto completo.

Pubblicato in Dove Stiamo Andando? | Lascia un commento

Wikipedia

Wikipedia si sostiene SOLO tramite donazioni e praticamente tutti l’abbiamo usata almeno una volta nella vita.
Non ha una riga di pubblicità, non vende dati, non ha abbonamenti, ma i server e la connettività costano.

non servono molti altri “perchè”, Fate una donazione.

http://it.wikipedia.org/

qui sotto il link diretto alla pagina per la donazione.
http://goo.gl/yA05x

Pubblicato in Dove Stiamo Andando? | Lascia un commento

OT (o quasi..) – passaggio di venere

dall’osservatorio di padova, fino alle 6:40 di domattina.

 
http://www.ustream.tv/embed/11170756

Live streaming by Ustream

su twitter

#nottedivenere oppure #venere

Pubblicato in Dove Stiamo Andando? | 1 commento

Sql Single Mode/Multi Mode

a volte succede di avere la necessità di mettere in single mode il DB, a me succede quando devo aggiornare (leggi aggiungi/modifica campi su) tabelle che hanno accessi continui.

ecco alcune righe di codice che possono dare una mano.

ALTER DATABASE <NomeDB> SET SINGLE_USER
ALTER TABLE <NomeDb>.dbo.<Tabella>
ADD <Campo> <TipoDato> NULL/NOT NULL
ALTER DATABASE <NomeDB> set MULTI_USER
Pubblicato in sql | Lascia un commento

TSQL – scrivere in un file di testo

finalmente dopo un pò di ricerche trovo da scopiazzare una stored che mi aiuti a scrivere in un file di testo.

non trovo il link all’articolo originale, ma ecco il codice.

come sempre qui, il repository con le ultime modifiche

CREATE PROCEDURE [dbo].[sp_AppendToFile] @FileName varchar(255), @Text1 varchar(255)
AS
BEGIN
DECLARE @FS int, @OLEResult int, @FileID int

 EXECUTE @OLEResult = sp_OACreate 'Scripting.FileSystemObject', @FS OUT
 IF @OLEResult <> 0 PRINT 'Scripting.FileSystemObject'
--Open a file
 execute @OLEResult = sp_OAMethod @FS, 'OpenTextFile', @FileID OUT, @FileName, 8, 1
 IF @OLEResult <> 0 PRINT 'OpenTextFile'
--Write Text1
 execute @OLEResult = sp_OAMethod @FileID, 'WriteLine', Null, @Text1
 IF @OLEResult <> 0 PRINT 'WriteLine'
EXECUTE @OLEResult = sp_OADestroy @FileID
 EXECUTE @OLEResult = sp_OADestroy @FS
END
Pubblicato in sql, Utilità, windows | Lascia un commento

Occhio alla virgola!

Ravanando in un foglio Excel, io e il mio fido capo abbiamo fatto una scoperta piuttosto inquietante.

una semplice operazione il cui risultato è ottenibile a mente senza sforzo, su Excel (ma direi su tutti i sistemi che trattano dati in virgola mobile) da il risultato sbagliato..

ebbene sì, e la prova arriva prestissimo, per fare la prova consiglio di usare i valori dello screenshot qui sotto, tenendo conto che nella cella C1 è presente la formula =A1-B1:

la differenza è 0,006… ma allora perchè la IF in D1 dice che C1 è maggiore di 0,06?!?!

semplice.. i dati in virgola mobile vengono rappresentati, come tutti i dati di un qualunque programma, in binario. Alcuni numeri non sono perfettamente rappresentabili in binario questo causa in qualche caso (non è regolare, dipende dal numero in se) aggiunge alla “N”esima cifra decimale un valore che però può causare dei problemi..

Aumentando infatti il numero di decimali della differenza fra A1 e B1 ecco cosa viene fuori…

ho fatto una prova anche con SQL e succede esattamente la stessa cosa

e se faccio il commercialista e devo fare dei conti al centesimo di EURO Come risolvo?!?!?

con un trucco del menga.. si memorizzano tutti i dati come interi (con gli interi il problema non sussiste) e si divide solo il risultato finale per 100..

ecco infatti qua sotto il risultato…

(in D5 è presente la stessa IF presente in D1)

Pubblicato in sql, Utilità | 3 commenti

controllo del nodo in caso di fail over su un cluster SQL

come controllare quando uno dei nodi del cluster cade?

prendendo (molto) spunto da un articolo apparso su SQLSERVER Central (sempre sia lodato) ho creato un pò di codice che verifica il nodo su cui l’istanza attuale sta girando.

in questa maniera è possibile confrontarla con una precedentemente salvata e poi decidere se inviare alert o quant’altro..

tutto si basa su questa riga di codice

exec master..xp_regread 'HKEY_LOCAL_Machine',
	'SYSTEM\CurrentControlSet\Control\ComputerName\ComputerName\',
	'ComputerName'

che permette di capire il nome macchina sulla quale sta girando attualmente il codice lanciato.

giocando un pò è venuto fuori il codice qui sotto:

se non la trova, crea una tabella nel MSDB chiamata UT_DBParameter

esegue poi il codice di cui sopra andando ad estrapolare il nome del nodo sulla quale sta girando l’istanza.

se questo è diverso da quello memorizzato allora invio una mail di allerta e memorizzo il nome del nodo attuale nella riga della mia istanza nella tabella UT_DBParameter

DECLARE @previous Nvarchar(50)
DECLARE @Actual Nvarchar(50)

DECLARE @Sbj NVarChar(200)
Set @Sbj ='IStanza ' + @@SERVERNAME
DECLARE @Bdy NVarChar(4000)
DECLARE @OperatorEmail nvarchar(100)
Set @OperatorEmail = (select email_address from msdb.dbo.sysoperators where name = 'operatore')   --** 

IF OBJECT_ID('MSDB..UT_DBParameters') is null
	BEGIN
		CREATE TABLE UT_DBParameters
		(
		Parametro NVARCHAR(50),
		Valore NVARCHAR(50)
		)
	END	

SELECT @previous = isnull(Valore,'') FROM UT_DBParameters
WHERE Parametro = @@ServerName

IF OBJECT_ID('tempdb..#PHYSICALHOSTNAME') is not null
	BEGIN
		drop table #PHYSICALHOSTNAME
	END	

CREATE TABLE #PHYSICALHOSTNAME
(
VALUE VARCHAR(30),
CURRENT_ACTIVE_NODE VARCHAR(30)
)

INSERT #PHYSICALHOSTNAME
exec master..xp_regread 'HKEY_LOCAL_Machine',
'SYSTEM\CurrentControlSet\Control\ComputerName\ComputerName\',
'ComputerName'

SELECT @Actual=CURRENT_ACTIVE_NODE FROM #PHYSICALHOSTNAME

IF  @previous <> @Actual
	BEGIN

		SET @Bdy = CHAR(13) + 'Istanza ' + @@SERVERNAME + ' passata dal nodo ' + @previous + ' al nodo ' + @Actual

		IF @Previous <> ''
			EXEC msdb.dbo.sp_send_dbmail  -- ***
					@profile_name = '4tsmailrobot'
					,@recipients = @OperatorEmail
					,@body = @Bdy
					,@subject = @Sbj

		Update Msdb..UT_DBParameters
		Set Valore = @Actual
		WHERE Parametro = @@ServerName

	END

NOTA

**operatore va sostituito con un operator valido per il server

*** si presuppone che il servizio di invio mail sia configurato..

Pubblicato in Server che passione, sql, Utilità | 1 commento

Conversione di un file di testo da UNIX a DOS/WINDOWS e Viceversa

ottimissimo tool..

http://www.sg-chem.net/u2win/

Pubblicato in Batch Caverna, Utilità, windows | Lascia un commento