I have the SP I call the following example ways (the call is not from SQL rather it is from a .net program)
or
-- run with a few grantees
exec someproc 99999, '<grantees><grantee id="99"/><grantee id="100"/><grantee id="101"/></grantees>'
-- takes about 1 sec with > 59s on xml decomp
or perhaps
-- run with lots of grantees (approx 2000)
exec someproc 99999, '<grantees><grantee id="99"/><grantee id="100"/>....<grantee id="2001"/></grantees>'
-- takes about 5 sec with > 4s on xml decomp
or perhaps
-- run with mega loads of grantees (approx 12000)
exec someproc 99999, '<grantees><grantee id="99"/><grantee id="100"/>....<grantee id="12001"/></grantees>'
-- takes about 1 min with > 59s on xml decomp
And I’m finding that the xml decomposition is the slowest part (about 96% of the query in each case – and believe me I’m inserting/deleting/altering tonnes of data in the rest of the proc).
I’m very curious if my way of decomposing XML is the most optimal way for the given input sets.
My criteria for using XML is simply to pass the SP a number of integers – so any suggestions for better ways are gratefully received.
create procedure someproc(@id int, @users xml = '<grantees/>') as
begin
-- decompose the users into a row set
declare @allUsers table (
id int
)
insert into @allUsers (id)
select distinct grantee.value('@id', 'int') uno
from @users.nodes('/grantees/grantee') grantees(grantee)
where isnull(grantee.value('@id', 'int'), 0) > 0
select * from @allUsers
-- other stuff happens
end
Since you can’t use a table parameter, try passing in a CSV sting and have the stored procedure split it into rows for you.
There are many ways to split string in SQL Server. This article covers the PROs and CONs of just about every method:
“Arrays and Lists in SQL Server 2005 and Beyond, When Table Value Parameters Do Not Cut it” by Erland Sommarskog
You need to create a split function. This is how a split function can be used:
I prefer the number table approach to split a string in TSQL but there are numerous ways to split strings in SQL Server, see the previous link, which explains the PROs and CONs of each.
For the Numbers Table method to work, you need to do this one time table setup, which will create a table
Numbersthat contains rows from 1 to 10,000:Once the Numbers table is set up, create this split function:
You can now easily split a CSV string into a table and join on it or use it however you need:
Just select the best string splitting function from the article (CLR, loop, whatever) that works with your large set of CSVs and you should get better performance.