Beruflich Dokumente
Kultur Dokumente
Case
I used a foreach loop to execute all my staging packages, but my server isn't using all resources. Is
there a way to execute multiple child packages at once, but with a loop?
Solution
The trick is to use a queue of packages and to have multiple 'processes' taking packages from the
queue to execute them. The number of packages that can be executed at a time depends on the
complexity of your packages. Staging packages for a single source are not complex, so a good
guideline/starting point is to execute one package per processor core.
1) The Queue
For this example I will use a FIFO (first in, first out) queue that is stored in a database table.
Alternatives could be the Windows Message Queue or the SQL Service Broker.
-- Create QUEUE table
1
CREATE TABLE [dbo].[FifoPackageQueue](
2
[Id] [bigint] IDENTITY(1,1) NOT NULL,
3
[Package] [varchar](50) NULL
4
) ON [PRIMARY]
5
6
7
8
9
10
11
12
13
14
GO
-- Add Index on Id
CREATE CLUSTERED INDEX cdxFifoPackageQueue on FifoPackageQueue (Id)
GO
-- Log tabel
CREATE TABLE [dbo].[FifoPackageQueueLog](
[Id] [bigint] IDENTITY(1,1) NOT NULL,
15
16
17
18
19
20
21
22
3) Fill Queue
In this example I will use an INSERT INTO SELECT query to get all staging packages from SSISDB.
You could also use regular INSERT queries or even a Foreach Loop or Script Task that loops through
a folder to add packages from the file system to the queue.
INSERT INTO CONV_LOG..FifoPackageQueue
1
(
2
[Package]
3
)
4
SELECT
Packages.[name]
5
FROM
[SSISDB].[internal].[packages] as Packages
6
INNER JOIN [SSISDB].[internal].[projects] as Projects
7
on Packages.project_version_lsn = Projects.object_version_lsn
8
9
10
WHERE
AND
Projects.name = 'MyProject'
Packages.name like 'STG%';
4) Execution Lines
Each Execution line starts with a Sequence Container connected to the Fill queue task. The
Precedence Constraint Expression is @[$Package::ParallelProcesses] >= 1 for the first and
@[$Package::ParallelProcesses] >= 2 for the second and so on.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
)
DELETE FROM cte
output deleted.Package INTO @TmpTable
-- Check if there is 1 record in temporary table
SELECT @PackageCount = count(*) FROM @TmpTable
if @PackageCount = 1
BEGIN
-- Return package name
SELECT Package FROM @TmpTable
END
ELSE
BEGIN
-- Temporary table was empty so queue was empty
-- Return empty string to stop next precedence constraint
SELECT '' as Package
END
6) For Loop
The For Loop loops until the package name is empty.
7) Log starttime
The first Execute SQL Task in the loop inserts the package name and a GETDATE() for the starttime
in the log table with an INSERT query. The variable containing the package name is a parameter for
this task. A very simple/basic log mechanisme. Adjust it to your needs or remove it if you have an
other log mechanism.
1 INSERT INTO FifoPackageQueueLog (Package, StartTime)
2 VALUES (?, GETDATE())
9) Log endtime
The second Execute SQL Task in the loop logs the enddate with an UPDATE query. The variable
containing the package name is a parameter for this task. The start- and enddate will help you choose
the optimal number of parallel tasks.
1 UPDATE FifoPackageQueueLog
2 SET EndTime = GETDATE()
3 WHERE Package = ?
4 AND EndTime is null
10) Get next package from queue
This is the exact same task/query as for getting the first package from the queue. If it can't find a
package in the queue then it will fill the variable with an empty string and the For Loop will stop.
11) Multiple Execution lines
Repeat steps 4 to 10 an x times. Probably a couple more then you have processor cores in your
server. Then start testing to find out the optimal number of parallel tasks.
12) Download example package
For SSIS 2012 I have added an example package for download. It contains 5 execution lines. Add
more if you have more cores available. The example is provided for educational purposes
only. This example package is not intended to be used in a production environment and has not been
tested in a production environment. Test it thoroughly before using it.
Note: you will find a similar solution in the 10 Tips and Tricks for Better SSIS
Performance presentation of David Peter Hansen and also in the SQL Rally Amsterdam presentation
of Davide Mauri about Automating DWH Patterns Through Metadata. This example package is
inspired by their solutions.