gennaio 2012 - Posts

SchemaBinding e tempo perso
31 gennaio 12 03.03 | abenedetti | with no comments

E un bel giorno alcuni report smisero di funzionare…

 

Faccio un passo indietro, ma lo scenario appena descritto è già molto chiaro.

Reports che accedono ad un db, lo interrogano andando direttamente sulle tabelle e ne presentano i dati.

 

Cosa succede se viene modificato il nome di una colonna utilizzata dal report?

Il report smette di funzionare, of course.

Ok, la domanda: abbiamo modo di dichiarare l’esistenza di una dipendenza di una certa struttura dati (ad esempio una tabella) rispetto a qualche altro oggetto (ad esempio un report)?

Si, utilizzando delle viste che, grazie all’opzione SCHEMABINDING, possano informare SQL Server di controllare ogni azione che verrà fatta sulle strutture fisiche sottostanti.

In questo modo, se la modifica invalida la vista, l’operazione di alter (o di drop) table fallisce (ed i nostri report continuano a funzionare).

Righe duplicate, righe univoche e Physloc
16 gennaio 12 06.08 | abenedetti | with no comments

Chi si è trovato, almeno una volta, di fronte a tabelle modellate male? ( quante mani alzate … :-) )

Ad esempio, di fronte a tabelle con righe duplicate, qualcosa come (un esempio stupido):

USE tempdb;
GO

CREATE TABLE test(
             col1 varchar( 3 ) , 
             col2 varchar( 3 ));
GO

INSERT INTO test
VALUES( 'aaa' , 'bbb' ) , 
      ( 'aaa' , 'bbb' ) , 
      ( 'aaa' , 'bbb' );
GO

SELECT
       *
  FROM test; 
GO

image

Come posso cancellare le righe che sono duplicate?

Direttamente, apparentemente, non posso…

Cosa intendo? Intendo dire che, per poter recuperare univocamente ciascuna riga, ho la necessità di “costruire” qualcosa che mi renda identificabile ciascuna tupla dalle altre.

Potrei usare la funzione ROW_NUMBER, ad esempio:

SELECT
       ROW_NUMBER( )
       OVER( ORDER BY col1 DESC )AS rowNum , 
       *
FROM test;
image

Oppure, prendendo spunto da qui, potrei usare la colonna virtuale [Physloc] in questo modo:

SELECT
       %%Physloc%% AS Physloc , 
       col1 , 
       col2
  FROM test;
GO
image

In questo modo, quindi, ottenendo il binary( 8 ) che rappresenta il PageID (primi 4 bytes), FileID (2 bytes) e Slot (2 bytes) ho sicuramente un’informazione univoca per ciascuna riga.

Datapage, physical storage location e fn_PhysLocFormatter
16 gennaio 12 10.10 | abenedetti | 1 comment(s)

In alcuni casi potrebbe essere utile conoscere la posizione fisica delle nostre righe.

In sostanza poter conoscere quale sia il “contenitore” che mantiene al suo interno la nostra informazione, le datapages che contengono i dati.

USE tempdb;
GO

CREATE TABLE anagrafica(
             idAnagrafica smallint , 
             cognome varchar( 35 ) , 
             nome varchar( 35 ));
GO

INSERT INTO anagrafica
VALUES( 1 , 'aaa' , 'bbb' ) , 
      ( 2 , 'ccc' , 'ddd' ) , 
      ( 3 , 'eee' , 'fff' );
GO

SELECT
       *
  FROM anagrafica; 
GO
image

A questo punto mettiamo il naso dentro le strutture che abbiamo creato:

SELECT
      %%Physloc%% as Physloc,
       sys.fn_PhysLocFormatter( %%Physloc%% )AS SysStorageLocation , 
       idAnagrafica, cognome, nome
  FROM anagrafica;

image

La “pseudo” colonna [Physloc] ci permette di vedere l’indirizzo univoco di ciascuna riga.

Grazie alla funzione (non documentata) fn_PhysLocFormatter possiamo formattare questo indirizzo in modo da visualizzare l’indirizzo fisico della riga.

Il risultato viene esposto come:

  • file num
  • datapage
  • slot

Una volta che otteniamo queste info, possiamo vedere le nostre pagine grazie al comando DBCC PAGE passando:

  • dbname / dbid
  • file num
  • page num
  • livello di informazioni che vogliamo (printopt)

Dove il “livello di informazioni” può essere:

  • 0 = header
  • 1 = header and hex dump for rows
  • 2 = header and the page dump
  • 3 = header and detail row information
DBCC TRACEON( 3604 );
DBCC PAGE('TempDB',1,114,2)
DBCC TRACEOFF( 3604 );
GO
image
SQL Server Consolidation Guidance
10 gennaio 12 07.23 | abenedetti | with no comments

Giusto per non perdere il link giusto, un withepaper molto interessante :-)

SQL Server Consolidation Guidance: qui.

The goal of this white paper is to provide a framework for choosing among virtualization, multi-database, and multi-instance consolidation strategies for SQL Server Database Engine OLTP applications.

SQL Server 2012 Filetable e Fulltext
09 gennaio 12 04.42 | abenedetti | with no comments

SQL Server 2012 aggiunge, alla funzionalità di FILESTREAM (tempo fa ne avevo parlato qui), la possibilità di interagire direttamente con le API di Windows, quindi consente ad un’applicazione di copiare dei files (e/o folder) in un path e lasciare al database engine tutta la sua gestione.

Diciamo che è il pezzo che mancava… :-)

Le cose interessanti, poi, sono diverse. Ne cito, per iniziare, due:

  • costruire dei trigger che intercettino copie di file “non voluti” e quindi intervenire “al volo”
  • gestire un catalogo fulltext e, quindi, indicizzare il contenuto dei files copiati e gestiti

Vediamo come fare…

/*
Enable and Configure FILESTREAM
http://msdn.microsoft.com/en-us/library/cc645923(v=sql.110).aspx

EXEC sp_configure Filestream_Access_level , 2;
RECONFIGURE;
GO
*/

USE MASTER;
GO

IF DB_ID( 'FileTableDB' )IS NOT NULL
    BEGIN
        DROP DATABASE FileTableDB;
    END;
GO

/*
Creazione del database
con FILESTREAM
*/
CREATE DATABASE FileTableDB ON PRIMARY
( 
    NAME = FileTableDB , 
    FILENAME = 'C:\SQL2012\db\FileTableDb\FileTableDB_Data.mdf' 
    ) , 
    FILEGROUP FileTableDBFS CONTAINS 
        FILESTREAM
        ( 
            NAME = FileTableDBFS , 
            FILENAME = 'C:\SQL2012\db\FileTableDb\FileTableDbFileStream'
        )
    LOG ON
    ( 
        NAME = FileTableDBLog , 
        FILENAME = 'C:\SQL2012\db\FileTableDb\FileTableDB_Log.ldf' 
    );
GO


/*
Specifico il livello di accesso non transazionale a livello di database
Questo per poter ottenere un file handle senza la necessità di una transazione
*/
ALTER DATABASE FileTableDB 
    SET FILESTREAM 
    ( 
    NON_TRANSACTED_ACCESS = FULL, DIRECTORY_NAME = N'FileTableDbFileStream'
    )
GO

/*
Passo al database utente
*/
USE FileTableDB;
GO

/*
Creo una tabella FileTable
*/
CREATE TABLE tblFileTableTest AS FileTable
WITH
(
        FileTable_Directory = 'tblFileTableTest',
        FileTable_Collate_Filename = database_default
)
GO

/*
A questo punto posso aprire una share di rete composta come:
\\nomeMacchina\nomeistanza\directoryName\fileTableDirectory

Quindi, nel mio caso, posso aprire:
\\Abalien\sql2012\FileTableDbFileStream\tblFileTableTest
*/

/* Ecco come posso recuperare il path alla document library: */
SELECT FileTableRootPath() AS 'FileTablePath' 
GO
image
/*
vedo la tabella (vuota)
*/
SELECT *
  FROM tblFileTableTest;
GO


/*
Aggiungo un trigger alla tabella perchè, per ipotesi,
voglio interrompere operazioni di copia se contenenti file TXT
*/
CREATE TRIGGER dbo.ControlFileTXT ON tblFileTableTest
    FOR INSERT , UPDATE
AS
IF EXISTS( SELECT 1
             FROM inserted
             WHERE inserted.file_type = 'txt' )
    BEGIN
        ROLLBACK;
    END;
GO

A questo punto posso fare drag & drop di files all’interno del mio folder e ritrovarli in tabella:

image

Oppure posso provare a copiare dei TXT e ricevere un errore di copia:

image

 

Fatto questo abilitiamo l’indicizzazione FULLTEXT sul nostro database e sulla nostra tabella:

/* Abilitiamo catalogo e indicizzazione FULLTEXT */
CREATE FULLTEXT CATALOG filetableCat;
GO

CREATE UNIQUE INDEX ui_document ON tblFileTableTest( stream_id );
GO

CREATE FULLTEXT INDEX ON tblFileTableTest
( file_stream TYPE COLUMN name LANGUAGE 1033 )
KEY INDEX ui_document ON filetableCat WITH CHANGE_TRACKING AUTO;
GO


/* Vediamo lo stato di indicizzazione */
SELECT CASE FULLTEXTCATALOGPROPERTY( 'filetableCat' , 'Populatestatus' )
       WHEN 0 THEN 'Idle'
       WHEN 1 THEN 'Full population in progress '
       WHEN 2 THEN 'Paused'
       WHEN 3 THEN 'Throttled'
       WHEN 4 THEN 'Recovering'
       WHEN 5 THEN 'Shutdown'
       WHEN 6 THEN 'Incremental population in progress'
       WHEN 7 THEN 'Building index'
       WHEN 8 THEN 'Disk is full. Paused.'
       WHEN 9 THEN 'Change tracking'
       END AS populateStatus , 
       CASE FULLTEXTCATALOGPROPERTY( 'filetableCat' , 'AccentSensitivity' )
       WHEN 0 THEN 'Accent insensitive'
       WHEN 1 THEN 'Accent sensitive'
       END AS AccentSensitivity , 
       FULLTEXTCATALOGPROPERTY( 'filetableCat' , 'ItemCount' )AS ItemCount;
GO

 

Attenzione: ricordiamoci che NON tutti i tipi di file sono immediatamente indicizzabili (per alcuni, come il PDF, serve installare il suo iFilter)

Per vedere le estensioni conosciute:

SELECT * FROM sys.fulltext_document_types;

image

Una volta copiati files nella nostra tabella filetable possiamo farne una ricerca testuale con una query come:

/* Test di ricerca */
DECLARE @SearchWord nvarchar( 300 );
SET @SearchWord = '"enabling end users"';

SELECT name
  FROM dbo.tblFileTableTest FT 
  JOIN CONTAINSTABLE
    ( dbo.tblFileTableTest , file_stream , @SearchWord ) AS T 
        ON FT.stream_id = T.[key];
GO
Upgrade Assistant for SQL Server 2012
09 gennaio 12 01.42 | abenedetti | with no comments

E’ disponibile in download qui il nuovo Upgrade Assistant per SQL Server 2012.

La pagina wiki del tool qui.

Database mail e dimensione query result
08 gennaio 12 03.41 | abenedetti | with no comments

Facendo un pò di manutenzione su alcuni job dei nostri server, trovo questo errore su uno di essi:

Executed as user: XXXXXXXXXXXXXx. File attachment or query results size exceeds allowable value of 1000000 bytes. [SQLSTATE 42000] (Error 22050).  The step failed.

Il job in questione effettua una semplice query ed invia, via mail, il suo risultato.

Qualcosa come questo:

EXEC msdb.dbo.sp_send_dbmail
@profile_name = 'XXXXXXXXXXXXxx',
@recipients = 'XXXXXXXXXXXXX',
@query = 'use myDatabase; SELECT … ‘,
@subject = '…..',
@query_result_no_padding =0;

 

Evidentemente (il messaggio è chiaro) il resultset è cresciuto a tal punto da eccedere la dimensione massima spedibile.

Come risolvo?

Apro la configurazione della mail (sul nodo “Management del SSMS, “Database Mail”, tasto dx, “Configure Database Mail”), “next” sulla prima videata, e poi “view or change system parameters”:

image

Quindi modifico il valore a mia descrizione:

image

Filed under: , , ,

This Blog

Syndication