Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 SQL Server 2000 Forums
 SQL Server Development (2000)
 The Cost of Splitting - UDFs

Author  Topic 

sureshot
Yak Posting Veteran

72 Posts

Posted - 2005-12-08 : 11:00:05
The need for splitting is giving me worse performance for my SP's than dynamic SQL. It's making me think long and hard about converting everything to SP's. I've tried both of the following split functions (with the unlim function needing a Numbers table but strangely having less that 1/3 the plan cost of the non-unlim one). They are both far slower than just a dynamic SQL (SQL3) though but I have no other good way to pass a list of values to an SP.


-- SQL1 Cost .0625 (22%)
delete externalgraderesults
from externalgraderesults r
join dbo.udf_SplitUnlim(@externalresultIdList,',') idlist on r.externalgraderesult_id=idlist.value

-- SQL2 Cost .207 (73.25%)
delete externalgraderesults
from externalgraderesults r
join dbo.udf_Split(@externalresultIdList,',') idlist on r.externalgraderesult_id=idlist.value

-- SQL3 Cost .0133 (4.7%)
delete
from externalgraderesults
where externalgraderesult_id in (18,122,131)


-- 7998 bytes max (but faster)
CREATE FUNCTION dbo.udf_Split (@param varchar(7998)) RETURNS TABLE AS
RETURN(SELECT substring(',' + @param + ',', Number + 1,
charindex(',', ',' + @param + ',', Number + 1) - Number - 1)
AS Value
FROM Numbers
WHERE Number <= len(',' + @param + ',') - 1
AND substring(',' + @param + ',', Number, 1) = ',')


-- Unlimited size
CREATE FUNCTION dbo.udf_SplitUnlim(@list ntext,
@delim nchar(1) = N',')
RETURNS @t TABLE (str varchar(4000),
nstr nvarchar(2000)) AS
BEGIN
DECLARE @slices TABLE (slice nvarchar(4000) NOT NULL)
DECLARE @slice nvarchar(4000),
@textpos int,
@maxlen int,
@stoppos int

SELECT @textpos = 1, @maxlen = 4000 - 2
WHILE datalength(@list) / 2 - (@textpos - 1) >= @maxlen
BEGIN
SELECT @slice = substring(@list, @textpos, @maxlen)
SELECT @stoppos = @maxlen - charindex(@delim, reverse(@slice))
INSERT @slices (slice) VALUES (@delim + left(@slice, @stoppos) + @delim)
SELECT @textpos = @textpos - 1 + @stoppos + 2 -- On the other side of the comma.
END
INSERT @slices (slice)
VALUES (@delim + substring(@list, @textpos, @maxlen) + @delim)

INSERT @t (str, nstr)
SELECT str, str
FROM (SELECT str = ltrim(rtrim(substring(s.slice, N.Number + 1,
charindex(@delim, s.slice, N.Number + 1) - N.Number - 1)))
FROM Numbers N
JOIN @slices s ON N.Number <= len(s.slice) - 1
AND substring(s.slice, N.Number, 1) = @delim) AS x

RETURN
END

Kristen
Test

22859 Posts

Posted - 2005-12-08 : 13:18:06
What are you basing your decision on - the percentage of the query plan used by the SPLIT function?

I would have thought that the number of LOGICAL Reads and Scans would be more "life-like"

You could try a splitter function that doesn't use charindex - e.g.

http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=55210&SearchTerms=Best+split+functions

Kristen
Go to Top of Page

sureshot
Yak Posting Veteran

72 Posts

Posted - 2005-12-08 : 17:18:02
I was basing it on the plan cpu cost. I'll look at the other splitter function as well and see what the reads are.
Go to Top of Page

sureshot
Yak Posting Veteran

72 Posts

Posted - 2005-12-08 : 18:55:10
I read the one you posted in your thread. I was curious why you were setting

-- sp_indexoption cannot be executed within a transaction block
EXEC sp_indexoption 'dbo.kk_MB_INT_Integer', 'disallowrowlocks', TRUE
EXEC sp_indexoption 'dbo.kk_MB_INT_Integer', 'disallowpagelocks', TRUE

Aren't you then forcing table locks? Isn't this bad for concurrency on a high traffic system?
Go to Top of Page

Kristen
Test

22859 Posts

Posted - 2005-12-09 : 01:40:32
That's only in the bit that inititally creates the table - a one time job. I had some issues with the code if I didn't use those, so a Ghastly Hack to work around them

"I was basing it on the plan cpu cost"

You might like to try this approach. Check the Logical Scans and Logical Reads, and work on the query until those two figures head for 1.

-- Clear cache (for level playing field
-- - only if wanting to check PHYSICAL performance rather than LOGICAL performance)
-- Do **NOT** run these on a Live server
DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE

-- Comment in the SHOWPLAN to see the Query Plan, OR the STATISTICS to see the logical stats
-- SET SHOWPLAN_TEXT ON
GO
-- SET STATISTICS IO ON; SET STATISTICS TIME ON

-- ... put query here - e.g.:

SELECT * FROM Northwind.dbo.Products

SET STATISTICS IO OFF; SET STATISTICS TIME OFF
GO
SET SET SHOWPLAN_TEXT OFF
GO

Kristen
Go to Top of Page
   

- Advertisement -