So far we’ve been looking at the cool stuff we can do with SQL Server Backups, Restores and PowerShell. And I don’t know about you, but it seems look like it’s going to make life a lot easier. But, is there a down side?

Well, as we’re DBA’s they first thing we usually worry about is performance. So let’s run some raw speed tests to see if there’s any unwanted overhead. For a backup, most of the overhead is going to be the speed of the underlying drives, so all these tests are run on the same rig. Which is SQL Server 2012 running on Windows 2012 in a VirtualBox virtual machine, PowerShell is 3.0.

We need a sizeable DB so we can get some decent timings. Nothing fancy here:

USE [master]
GO
CREATE DATABASE [SpeedTest]
 CONTAINMENT = NONE
 ON  PRIMARY
( NAME = N'SpeedTest', FILENAME = N'E:\speedtest\SpeedTest.mdf')
 LOG ON
( NAME = N'SpeedTest_log', FILENAME = N'E:\speedtest\SpeedTest_log.ldf')
GO
USE [SpeedTest]
GO
CREATE TABLE [dbo].[bigtable1](
	[dummyID] [int] IDENTITY(1,1) NOT NULL,
	[bigdatat] [varchar](8000) NULL
) ON [PRIMARY]

GO
SET ANSI_PADDING OFF
GO
/****** Object:  Table [dbo].[bigtable2]    Script Date: 24/09/2013 15:05:49 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[bigtable2](
	[dummyID] [int] IDENTITY(1,1) NOT NULL,
	[bigdatat] [varchar](8000) NULL
) ON [PRIMARY]

GO

CREATE TABLE [dbo].[bigtable3](
	[dummyID] [int] IDENTITY(1,1) NOT NULL,
	[bigdatat] [varchar](8000) NULL
) ON [PRIMARY]

GO

CREATE TABLE [dbo].[bigtable4](
	[dummyID] [int] IDENTITY(1,1) NOT NULL,
	[bigdatat] [varchar](8000) NULL
) ON [PRIMARY]

GO

And then bloat the tables with junk:

insert into Bigtable1 (bigdatat) values (replicate('junk',2000))
insert into Bigtable2 (bigdatat) values (replicate('junk',2000))
insert into Bigtable3 (bigdatat) values (replicate('junk',2000))
insert into Bigtable4 (bigdatat) values (replicate('junk',2000))
go 100000

Which gives us a database of 3GB. Tiny in the real world sense, but large enough to give us some usable stats.

To get the T-SQL timings we use the following script:

create table backuptime(
ident integer,
starttime datetime,
endtime datetime
)

declare @i integer  =1;

while @i<20
begin
    declare @starttime datetime, @endtime datetime;
    set @starttime = CURRENT_TIMESTAMP
    backup database Speedtest to disk='e:\sizetest\backup.bak' with init
    select @endtime = current_timestamp
    insert into backuptime values (@i,@starttime,@endtime)
    set @i = @i+1
end

We create a holding table, and then loop through 20 backups recording the start and finish times in our table.

And to get our PowerShell timings:

Import-Module SQLPS -DisableNameChecking

$Database = "SpeedTest"
$ServerName = "WIN-C0BP65U3D4G"

$SQLSvr = New-Object -TypeName  Microsoft.SQLServer.Management.Smo.Server($ServerName)
$Db = New-Object -TypeName Microsoft.SqlServer.Management.Smo.Database
$Db = $SQLSvr.Databases.Item($Database)
$BackupName = "e:\sizetest\speedtestps.bak"
$DeviceType = [Microsoft.SqlServer.Management.Smo.DeviceType]::File

$i=1

$times = @()

while ($i -lt 20){
    $StartTime = get-date
    $Backup = New-Object -TypeName Microsoft.SqlServer.Management.Smo.Backup
    $Backup.Initialize = $True

    $Backup.Action = [Microsoft.SQLServer.Management.SMO.BackupActionType]::Database
    $Backup.Database = $db.Name

    $BackupDevice = New-Object -TypeName Microsoft.SQLServer.Management.Smo.BackupDeviceItem($BackupName,$DeviceType)

    $Backup.Devices.Add($BackupDevice)
    $Backup.SqlBackup($SQLSvr)
    $Backup.Devices.Remove($BackupDevice)

    remove-variable backup
    $times += new-timespan $StartTime $(get-date)
    $i++
}

We create the connection to SQL Server outside of our loop, as this would be the most costly part of the script but is only realy needed once for each connection to the server. The backup runs the same Full backup as our T-SQL version. We use the New-TimeSpan cmdlet to calculate the interval between start and finish, then store that in an array which we can later analyse through Measure-Object to get maximum, minimum and average.

So after running each procedure 3 times to get a consistent average what did we find?

From the T-SQL runs I got an average of 48.18s, with a longest of 55.59s, shortest of 45.94s and a standard deviation of 1.42s (Full result data here)

And from the PowerShell runs I got an average of 58.56s, with a longest of 72.91s, shortest of 56.48s and a standard deviation of 2.1s (Full result data here)

So PowerShell appears slower here. It’s certainly more variable (greater spread between max and min, and a larger Standard deviation means in general the times are across a general range ignoring the extremes).

Not looking great at the moment. So lets try doubling the size of the database and see if the differences stay consistent. Just rerun the insert block again. This time I’m just going to run the timings once each

Now the T-SQL runs give me an average of 111.8s, max of 118.59s, minimum of 107.87s and a standard deviation of 2.16s (Full result data here)

And PowerShell gives me an average of 110.48s, max of 121.1s, minimum of 107s and a standard deviation of 2.78s (Full result data here)

So now it shows that they’re pretty much even. Which shows that the PowerShell overhead is in creating the object and then sending it to a remote server

Hopefully that’s put some minds at rest about any potential performance issues using these PowerShell backup and restore methods over the more convential SQL Server methods.

This post is part of a series posted between 1st September 2013 and 3rd October 2013, an index for the series is available here.

T-SQL Backups time results

starttime endtime Time difference (ms)
24/09/2013 15:24:23 24/09/2013 15:25:19 55593
24/09/2013 15:25:19 24/09/2013 15:26:07 47823
24/09/2013 15:26:07 24/09/2013 15:26:54 47363
24/09/2013 15:26:54 24/09/2013 15:27:42 48213
24/09/2013 15:27:42 24/09/2013 15:28:30 47576
24/09/2013 15:28:30 24/09/2013 15:29:17 46646
24/09/2013 15:29:17 24/09/2013 15:30:03 46326
24/09/2013 15:30:03 24/09/2013 15:30:51 48476
24/09/2013 15:30:51 24/09/2013 15:31:39 47656
24/09/2013 15:31:39 24/09/2013 15:32:26 46546
24/09/2013 15:32:26 24/09/2013 15:33:13 47756
24/09/2013 15:33:13 24/09/2013 15:34:01 47716
24/09/2013 15:34:01 24/09/2013 15:34:47 45940
24/09/2013 15:34:47 24/09/2013 15:35:35 47993
24/09/2013 15:35:35 24/09/2013 15:36:24 49250
24/09/2013 15:36:24 24/09/2013 15:37:14 50020
24/09/2013 15:37:14 24/09/2013 15:38:03 48333
24/09/2013 15:38:03 24/09/2013 15:38:51 48286
24/09/2013 15:38:51 24/09/2013 15:39:39 48086
24/09/2013 16:32:19 24/09/2013 16:33:06 47543
24/09/2013 16:33:06 24/09/2013 16:33:54 48000
24/09/2013 16:33:54 24/09/2013 16:34:41 47250
24/09/2013 16:34:41 24/09/2013 16:35:30 48350
24/09/2013 16:35:30 24/09/2013 16:36:17 47543
24/09/2013 16:36:17 24/09/2013 16:37:05 47426
24/09/2013 16:37:05 24/09/2013 16:37:52 47296
24/09/2013 16:37:52 24/09/2013 16:38:40 48030
24/09/2013 16:38:40 24/09/2013 16:39:29 49056
24/09/2013 16:39:29 24/09/2013 16:40:15 46010
24/09/2013 16:40:15 24/09/2013 16:41:02 46876
24/09/2013 16:41:02 24/09/2013 16:41:49 47360
24/09/2013 16:41:49 24/09/2013 16:42:37 47286
24/09/2013 16:42:37 24/09/2013 16:43:26 49096
24/09/2013 16:43:26 24/09/2013 16:44:13 47810
24/09/2013 16:44:13 24/09/2013 16:45:01 47183
24/09/2013 16:45:01 24/09/2013 16:45:48 47423
24/09/2013 16:45:48 24/09/2013 16:46:36 47953
24/09/2013 16:46:36 24/09/2013 16:47:24 48056
25/09/2013 07:32:54 25/09/2013 07:33:42 47663
25/09/2013 07:33:42 25/09/2013 07:34:30 47906
25/09/2013 07:34:30 25/09/2013 07:35:19 49300
25/09/2013 07:35:19 25/09/2013 07:36:08 48623
25/09/2013 07:36:08 25/09/2013 07:36:55 47323
25/09/2013 07:36:55 25/09/2013 07:37:44 49240
25/09/2013 07:37:44 25/09/2013 07:38:34 49756
25/09/2013 07:38:34 25/09/2013 07:39:23 48940
25/09/2013 07:39:23 25/09/2013 07:40:12 48746
25/09/2013 07:40:12 25/09/2013 07:40:59 47420
25/09/2013 07:40:59 25/09/2013 07:41:47 48020
25/09/2013 07:41:47 25/09/2013 07:42:35 47773
25/09/2013 07:42:35 25/09/2013 07:43:25 50163
25/09/2013 07:43:25 25/09/2013 07:44:16 51130
25/09/2013 07:44:16 25/09/2013 07:45:05 48266
25/09/2013 07:45:05 25/09/2013 07:45:53 48846
25/09/2013 07:45:53 25/09/2013 07:46:42 49130
25/09/2013 07:46:42 25/09/2013 07:47:32 49333
25/09/2013 07:47:32 25/09/2013 07:48:19 47490

PowerShell Backup Time results

Time difference (s)
57.30
56.48
59.92
57.85
57.72
57.99
58.43
57.15
57.75
57.57
58.08
57.57
57.92
58.24
58.85
59.68
57.91
58.89
56.84
58.23
59.27
58.78
58.26
58.18
57.62
59.20
58.96
57.80
57.94
57.56
58.80
57.45
56.66
59.02
59.24
58.72
57.96
58.11
72.91
59.89
58.91
58.84
58.52
59.15
59.22
58.59
57.33
58.93
58.23
58.58
58.37
58.10
60.17
58.09
58.15
56.82
59.31

T-SQL Results, 6GB database

StartTime EndTime Difference(ms)
2013-09-25 09:42:18.563 2013-09-25 09:44:17.153 118590
2013-09-25 09:44:17.160 2013-09-25 09:46:08.480 111320
2013-09-25 09:46:08.480 2013-09-25 09:47:58.923 110443
2013-09-25 09:47:58.923 2013-09-25 09:49:46.793 107870
2013-09-25 09:49:46.793 2013-09-25 09:51:38.323 111530
2013-09-25 09:51:38.323 2013-09-25 09:53:28.560 110236
2013-09-25 09:53:28.560 2013-09-25 09:55:21.393 112833
2013-09-25 09:55:21.393 2013-09-25 09:57:11.690 110296
2013-09-25 09:57:11.690 2013-09-25 09:59:03.420 111730
2013-09-25 09:59:03.420 2013-09-25 10:00:56.600 113180
2013-09-25 10:00:56.600 2013-09-25 10:02:48.073 111473
2013-09-25 10:02:48.073 2013-09-25 10:04:38.913 110840
2013-09-25 10:04:38.913 2013-09-25 10:06:30.870 111956
2013-09-25 10:06:30.870 2013-09-25 10:08:23.490 112620
2013-09-25 10:08:23.490 2013-09-25 10:10:16.580 113090
2013-09-25 10:10:16.580 2013-09-25 10:12:08.380 111800
2013-09-25 10:12:08.380 2013-09-25 10:14:02.007 113626
2013-09-25 10:14:02.007 2013-09-25 10:15:51.490 109483
2013-09-25 10:15:51.490 2013-09-25 10:17:42.697 111206

PowerShell results 6GB database

Time (s)
121.08
111.15
110.59
110.47
109.39
109.23
110.79
109.87
110.14
109.96
110.59
107.47
109.18
110.67
109.81
110.96
110.46
110.38
106.99