Lavorando con applicazioni database mi rendo conto che c’è una fase importantissima che troppo spesso viene trascurata: il test delle performance sui presunti carichi che si dovranno sostenere.
Mi spiego con una domanda: qual 'è il senso di testare le nostre applicazioni con due, cinque, dieci righe nelle tabelle?
(per poi sentirsi dire… ma in sviluppo andava tutto veloce…)
Forse, uno dei problemi, è quello di riuscire ad inserire righe in un numero simile a quelle che avremo sui nostri sistemi di produzione.
Certamente possiamo evitare di fare questa attività a mano.
Con qualche riga di codice possiamo costruire una procedura che, preso in ingresso il nome della tabella (schema e nome) ed un numero di righe, riempia di valori fittizzi le nostre colonne consentendoci di avere strutture, in test, di dimensioni almeno simili all’ambiente finale.
Questo il codice:
IF EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND name = 'up_insertDummyData')DROP PROCEDURE dbo.up_insertDummyDataGO CREATE PROCEDURE dbo.up_insertDummyData(@schemaName nvarchar( 250 ) , @tableName nvarchar( 250 ) , @nr int )AS BEGIN SET NOCOUNT ON;DECLARE @i int = 0, @tsql varchar( max ) = '';WHILE (@i < @nr)BEGIN SELECT @tsql = @tsql + CASE WHEN c.column_id = 1 THEN 'INSERT ' + @schemaName + '.[' + t.name + '] VALUES ( 'ELSE ''END + CASE WHEN c.is_identity = 0 THEN CASE WHEN y.name IN ( 'bit' , 'bigint' , 'int' , 'smallint' , 'tinyint' , 'float' , 'decimal' , 'numeric' , 'money' , 'smallmoney' , 'real' )THEN SUBSTRING( CAST(1000*RAND() AS VARCHAR(50)) , 1 , c.max_length)WHEN y.name IN ( 'binary' , 'varbinary' ) THEN SUBSTRING( '0x546869732069732044756D6D792044617461' , 1, c.max_length )WHEN y.name IN ( 'varchar' , 'char' , 'text', 'nchar' , 'nvarchar' , 'ntext' ) THEN '''' + SUBSTRING( 'some data some data some data' , 1 , c.max_length /2 ) + ''''WHEN y.name IN ( 'date' , 'time' , 'datetime' , 'datetime2' , 'smalldatetime' , 'datetimeoffset' ) THEN '''' + CONVERT( varchar( 25 ) , GETDATE( ) , 121 ) + ''''WHEN y.name IN ( 'uniqueidentifier' ) THEN '''' + CAST( NEWID( ) AS varchar( 36 )) + ''''ELSE '' END + CASE WHEN c.column_id = (SELECT MAX( column_id ) FROM sys.columns WHERE OBJECT_ID = c.OBJECT_ID )THEN ');'ELSE ','END ELSE ''END FROM sys.tables AS t INNER JOIN sys.schemas s ON t.schema_id = s.schema_idINNER JOIN sys.columns c ON t.OBJECT_ID = c.OBJECT_IDINNER JOIN sys.types AS y ON c.user_type_id = y.user_type_idWHERE t.name = @tableName AND s.name = @schemaNameSET @i+=1;EXEC ( @tsql );SET @tsql = '';END END;GO
Un esempio di utilizzo:
--> Test Procedure:EXEC dbo.up_insertDummyData @schemaName = 'dbo', @tableName = 'lineItem' , @nr = 100000;
I nostri dati di test:
--> View dataSELECT count(*) from lineitemSELECT record_count, avg_record_size_in_bytes, page_count FROM sys.dm_db_index_physical_stats( DB_ID( ) , OBJECT_ID( 'lineItem' ) , -1 , NULL , 'detailed' );EXEC sp_spaceused 'lineItem'SELECT TOP 2 * FROM lineitem GO