Performance issue with tally solution

  • Adam Machanic (4/27/2009)


    Florian Reischl (4/27/2009)


    Thanks for the new version! I also supposed that a char array should perform better than the string. The current test results show the opposite though...

    Did you try my new version in your tests? Or are you referring to the char array solution already posted here? I'm assuming the latter since the test results you just posted appear to be unchanged from your previous post... Please give the new version a try. In my tests against my previous split method my new one is performing consistently 12-15% faster, both under load and in solitary tests on an empty server.

    Er... *cough*

    ... it happened automatically! The voices told me to do it...

    Apologize! I couldn't just copy paste the code from your page since the names didn't fit with my test environment. The first test environment I had in this thread became completely unusable because I copied all names of all functions. So I copied the code blocks but into own methods and I noticed the memory copies within your code and fixed it... Again, it happened automatically... Sorry!

    Here my modified code:

    using System;

    using System.Collections;

    using System.Data;

    using System.Data.SqlClient;

    using System.Data.SqlTypes;

    using Microsoft.SqlServer.Server;

    public partial class UserDefinedFunctions

    {

    [Microsoft.SqlServer.Server.SqlFunction(

    FillRowMethodName="FillRow_SplitString_Enumerator",

    TableDefinition="item nvarchar(max)"

    )

    ]

    public static IEnumerator ufn_clr_SplitString_Enumerator_FR(

    [SqlFacet(

    IsFixedLength=false,

    IsNullable=false,

    MaxSize=-1

    )

    ]

    SqlString strIn,

    [SqlFacet(

    IsFixedLength=true,

    IsNullable=false,

    MaxSize=1

    )

    ]

    SqlString delimiter

    )

    {

    return new SplitStringEnumerator(strIn.Value, delimiter.Value[0]);

    }

    public static void FillRow_SplitString_Enumerator(object obj, out SqlString item)

    {

    item = new SqlString((string)obj);

    }

    public class SplitStringEnumerator : IEnumerator

    {

    public SplitStringEnumerator(string theString, char delimiter)

    {

    this._theString = theString;

    this._delimiter = delimiter;

    this._lastPos = -1;

    this._nextPos = -1;

    }

    #region IEnumerator Members

    public object Current

    {

    get { return _theString.Substring(_lastPos, _nextPos - _lastPos).Trim(); }

    }

    public bool MoveNext()

    {

    if (_nextPos >= _theString.Length)

    return false;

    else

    {

    _lastPos = _nextPos + 1;

    if (_lastPos == _theString.Length)

    return false;

    _nextPos = _theString.IndexOf(_delimiter, _lastPos);

    if (_nextPos == -1)

    _nextPos = _theString.Length;

    return true;

    }

    }

    public void Reset()

    {

    this._lastPos = -1;

    this._nextPos = -1;

    }

    #endregion

    private int _lastPos;

    private int _nextPos;

    private string _theString;

    private char _delimiter;

    }

    };

    I added both of your methods to my tests (now without changes!). I named your first (from your page) "CLR String Enumerator Adam1" and the second (posted here) "CLR String Enumerator Adam2". My version is called "CLR String Enumerator FR".

    Anyway, it still seems that the old works faster than the new one. I also will look a little bit deeper into both.

    Results:

    ItemLength ItemCount ItemRows ItemType ItemDescription Ranking Module Duration(ms) CpuTime

    ----------- ----------- ----------- -------------- ---------------- ------- ---------------------------- ------------ -------

    10 10 10 VARCHAR(111) Fixed Length 1 Traditional Tally TOP(0) 00:00:00.003 15

    10 10 10 VARCHAR(111) Fixed Length 2 CLR char loop 00:00:00.007 0

    10 10 10 VARCHAR(111) Fixed Length 3 CLR Simple 00:00:00.007 16

    10 10 10 VARCHAR(111) Fixed Length 4 CLR String Enumerator FR 00:00:00.007 15

    10 10 10 VARCHAR(111) Fixed Length 5 CLR String Enumerator Adam1 00:00:00.007 0

    10 10 10 VARCHAR(111) Fixed Length 6 CLR String Enumerator Adam2 00:00:00.007 16

    10 10 10 VARCHAR(111) Fixed Length 7 CLR RegEx 00:00:00.010 0

    10 10 10 VARCHAR(111) Fixed Length 8 CLR XML 00:00:00.043 16

    10 10 10 VARCHAR(111) Fixed Length 9 Cursor 00:00:00.043 15

    10 10 10 VARCHAR(111) Fixed Length 10 Traditional Tally 00:00:00.190 16

    10 10 1000 VARCHAR(111) Fixed Length 1 Traditional Tally TOP(0) 00:00:00.133 125

    10 10 1000 VARCHAR(111) Fixed Length 2 Traditional Tally 00:00:00.257 141

    10 10 1000 VARCHAR(111) Fixed Length 3 CLR String Enumerator FR 00:00:00.403 390

    10 10 1000 VARCHAR(111) Fixed Length 4 CLR String Enumerator Adam1 00:00:00.407 406

    10 10 1000 VARCHAR(111) Fixed Length 5 CLR String Enumerator Adam2 00:00:00.440 453

    10 10 1000 VARCHAR(111) Fixed Length 6 CLR char loop 00:00:00.440 437

    10 10 1000 VARCHAR(111) Fixed Length 7 CLR Simple 00:00:00.447 437

    10 10 1000 VARCHAR(111) Fixed Length 8 CLR RegEx 00:00:00.460 484

    10 10 1000 VARCHAR(111) Fixed Length 9 CLR XML 00:00:00.637 577

    10 10 1000 VARCHAR(111) Fixed Length 10 Cursor 00:00:00.687 718

    10 10 10000 VARCHAR(111) Fixed Length 1 Traditional Tally TOP(0) 00:00:01.227 1217

    10 10 10000 VARCHAR(111) Fixed Length 2 Traditional Tally 00:00:01.593 1311

    10 10 10000 VARCHAR(111) Fixed Length 3 CLR String Enumerator FR 00:00:04.023 4181

    10 10 10000 VARCHAR(111) Fixed Length 4 CLR String Enumerator Adam1 00:00:04.037 4134

    10 10 10000 VARCHAR(111) Fixed Length 5 CLR String Enumerator Adam2 00:00:04.390 4509

    10 10 10000 VARCHAR(111) Fixed Length 6 CLR char loop 00:00:04.400 4461

    10 10 10000 VARCHAR(111) Fixed Length 7 CLR Simple 00:00:04.427 4539

    10 10 10000 VARCHAR(111) Fixed Length 8 CLR RegEx 00:00:04.530 4649

    10 10 10000 VARCHAR(111) Fixed Length 9 CLR XML 00:00:05.773 5491

    10 10 10000 VARCHAR(111) Fixed Length 10 Cursor 00:00:06.607 6739

    100 10 10 VARCHAR(1011) Fixed Length 1 CLR String Enumerator FR 00:00:00.007 15

    100 10 10 VARCHAR(1011) Fixed Length 2 CLR String Enumerator Adam1 00:00:00.007 16

    100 10 10 VARCHAR(1011) Fixed Length 3 CLR String Enumerator Adam2 00:00:00.007 0

    100 10 10 VARCHAR(1011) Fixed Length 4 Traditional Tally TOP(0) 00:00:00.010 15

    100 10 10 VARCHAR(1011) Fixed Length 5 CLR Simple 00:00:00.010 16

    100 10 10 VARCHAR(1011) Fixed Length 6 CLR RegEx 00:00:00.010 0

    100 10 10 VARCHAR(1011) Fixed Length 7 Cursor 00:00:00.013 16

    100 10 10 VARCHAR(1011) Fixed Length 8 CLR char loop 00:00:00.027 16

    100 10 10 VARCHAR(1011) Fixed Length 9 CLR XML 00:00:00.053 31

    100 10 10 VARCHAR(1011) Fixed Length 10 Traditional Tally 00:00:00.503 16

    100 10 100 VARCHAR(1011) Fixed Length 1 CLR String Enumerator FR 00:00:00.053 62

    100 10 100 VARCHAR(1011) Fixed Length 2 CLR String Enumerator Adam1 00:00:00.057 47

    100 10 100 VARCHAR(1011) Fixed Length 3 CLR String Enumerator Adam2 00:00:00.057 62

    100 10 100 VARCHAR(1011) Fixed Length 4 CLR Simple 00:00:00.057 63

    100 10 100 VARCHAR(1011) Fixed Length 5 CLR RegEx 00:00:00.057 47

    100 10 100 VARCHAR(1011) Fixed Length 6 CLR char loop 00:00:00.083 47

    100 10 100 VARCHAR(1011) Fixed Length 7 Traditional Tally TOP(0) 00:00:00.087 63

    100 10 100 VARCHAR(1011) Fixed Length 8 CLR XML 00:00:00.093 62

    100 10 100 VARCHAR(1011) Fixed Length 9 Cursor 00:00:00.123 93

    100 10 100 VARCHAR(1011) Fixed Length 10 Traditional Tally 00:00:00.357 94

    100 10 1000 VARCHAR(1011) Fixed Length 1 CLR String Enumerator FR 00:00:00.483 530

    100 10 1000 VARCHAR(1011) Fixed Length 2 CLR String Enumerator Adam1 00:00:00.520 484

    100 10 1000 VARCHAR(1011) Fixed Length 3 CLR String Enumerator Adam2 00:00:00.523 530

    100 10 1000 VARCHAR(1011) Fixed Length 4 CLR Simple 00:00:00.527 577

    100 10 1000 VARCHAR(1011) Fixed Length 5 CLR RegEx 00:00:00.557 546

    100 10 1000 VARCHAR(1011) Fixed Length 6 Traditional Tally TOP(0) 00:00:00.627 655

    100 10 1000 VARCHAR(1011) Fixed Length 7 CLR char loop 00:00:00.630 499

    100 10 1000 VARCHAR(1011) Fixed Length 8 CLR XML 00:00:00.653 656

    100 10 1000 VARCHAR(1011) Fixed Length 9 Cursor 00:00:00.847 874

    100 10 1000 VARCHAR(1011) Fixed Length 10 Traditional Tally 00:00:00.920 686

    100 10 100 NVARCHAR(1011) Fixed Length 1 CLR String Enumerator Adam1 00:00:00.050 63

    100 10 100 NVARCHAR(1011) Fixed Length 2 CLR String Enumerator FR 00:00:00.053 62

    100 10 100 NVARCHAR(1011) Fixed Length 3 CLR String Enumerator Adam2 00:00:00.057 62

    100 10 100 NVARCHAR(1011) Fixed Length 4 CLR Simple 00:00:00.057 62

    100 10 100 NVARCHAR(1011) Fixed Length 5 CLR RegEx 00:00:00.057 62

    100 10 100 NVARCHAR(1011) Fixed Length 6 CLR char loop 00:00:00.077 47

    100 10 100 NVARCHAR(1011) Fixed Length 7 Traditional Tally TOP(0) 00:00:00.093 78

    100 10 100 NVARCHAR(1011) Fixed Length 8 CLR XML 00:00:00.100 78

    100 10 100 NVARCHAR(1011) Fixed Length 9 Cursor 00:00:00.140 109

    100 10 100 NVARCHAR(1011) Fixed Length 10 Traditional Tally 00:00:00.200 93

    100 10 1000 NVARCHAR(1011) Fixed Length 1 CLR String Enumerator FR 00:00:00.483 514

    100 10 1000 NVARCHAR(1011) Fixed Length 2 CLR String Enumerator Adam1 00:00:00.493 515

    100 10 1000 NVARCHAR(1011) Fixed Length 3 CLR String Enumerator Adam2 00:00:00.527 578

    100 10 1000 NVARCHAR(1011) Fixed Length 4 CLR RegEx 00:00:00.537 562

    100 10 1000 NVARCHAR(1011) Fixed Length 5 CLR Simple 00:00:00.543 562

    100 10 1000 NVARCHAR(1011) Fixed Length 6 CLR char loop 00:00:00.593 530

    100 10 1000 NVARCHAR(1011) Fixed Length 7 Traditional Tally TOP(0) 00:00:00.723 733

    100 10 1000 NVARCHAR(1011) Fixed Length 8 CLR XML 00:00:00.740 562

    100 10 1000 NVARCHAR(1011) Fixed Length 9 Cursor 00:00:00.840 842

    100 10 1000 NVARCHAR(1011) Fixed Length 10 Traditional Tally 00:00:01.270 780

    1000 10 10 NVARCHAR(MAX) Fixed Length 1 CLR Simple 00:00:00.010 16

    1000 10 10 NVARCHAR(MAX) Fixed Length 2 CLR RegEx 00:00:00.010 0

    1000 10 10 NVARCHAR(MAX) Fixed Length 3 CLR String Enumerator FR 00:00:00.010 16

    1000 10 10 NVARCHAR(MAX) Fixed Length 4 CLR String Enumerator Adam1 00:00:00.010 15

    1000 10 10 NVARCHAR(MAX) Fixed Length 5 CLR String Enumerator Adam2 00:00:00.010 16

    1000 10 10 NVARCHAR(MAX) Fixed Length 6 CLR char loop 00:00:00.047 0

    1000 10 10 NVARCHAR(MAX) Fixed Length 7 CLR XML 00:00:00.050 15

    1000 10 10 NVARCHAR(MAX) Fixed Length 8 Cursor 00:00:00.053 31

    1000 10 10 NVARCHAR(MAX) Fixed Length 9 Traditional Tally TOP(0) 00:00:00.540 515

    1000 10 10 NVARCHAR(MAX) Fixed Length 10 Traditional Tally 00:00:00.833 499

    1000 10 100 NVARCHAR(MAX) Fixed Length 1 CLR String Enumerator FR 00:00:00.090 78

    1000 10 100 NVARCHAR(MAX) Fixed Length 2 CLR Simple 00:00:00.097 78

    1000 10 100 NVARCHAR(MAX) Fixed Length 3 CLR String Enumerator Adam2 00:00:00.097 78

    1000 10 100 NVARCHAR(MAX) Fixed Length 4 CLR char loop 00:00:00.107 78

    1000 10 100 NVARCHAR(MAX) Fixed Length 5 CLR RegEx 00:00:00.113 78

    1000 10 100 NVARCHAR(MAX) Fixed Length 6 CLR String Enumerator Adam1 00:00:00.150 62

    1000 10 100 NVARCHAR(MAX) Fixed Length 7 CLR XML 00:00:00.153 156

    1000 10 100 NVARCHAR(MAX) Fixed Length 8 Cursor 00:00:00.313 250

    1000 10 100 NVARCHAR(MAX) Fixed Length 9 Traditional Tally TOP(0) 00:00:04.977 5148

    1000 10 100 NVARCHAR(MAX) Fixed Length 10 Traditional Tally 00:00:05.323 5054

    Greets

    Flo

  • Hmm, something you've changed is making your version an order of magnitude slower on my test system than either of my versions. Here's a simple test I'm running:

    --Set up a test table

    create table #z (y varchar(max))

    insert #z select replicate(convert(varchar(max), 'abcd,'), 1000000)

    --Wall clock time for each of the methods

    --Adam1

    declare @d datetime

    set @d = getdate()

    select count(*) from #z

    cross apply dbo.faster_split(y, ',') q

    select datediff(ms, @d, getdate()) AS Adam1

    go

    --Adam2

    declare @d datetime

    set @d = getdate()

    select count(*) from #z

    cross apply dbo.even_faster(y, ',') q

    select datediff(ms, @d, getdate()) AS Adam2

    go

    --FR

    declare @d datetime

    set @d = getdate()

    select count(*) from #z

    cross apply dbo.ufn_clr_SplitString_Enumerator_FR(y, ',') q

    select datediff(ms, @d, getdate()) AS FR

    go

    Results, on my SQL Server 2008 server:

    Adam1: ~1350

    Adam2: ~1100

    FR: ~13000 (that additional zero is not a typo)

    Odd...

    --
    Adam Machanic
    whoisactive

  • Adam Machanic (4/27/2009)


    Hmm, something you've changed is making your version an order of magnitude slower on my test system than either of my versions.

    OK, found it. Make your return type NVARCHAR(4000), not NVARCHAR(MAX). And while you're at it, ditch that _ syntax for locals, please for the love of readable code!!! 🙂

    --
    Adam Machanic
    whoisactive

  • Really strange...

    I copied exactly your script (just changed the names of the functions):

    Adam1: 15546

    Adam2: 15380

    FR: 15550

    System:

    Microsoft SQL Server 2008 (SP1) - 10.0.2531.0 (X64)

    Mar 29 2009 10:11:52

    Copyright (c) 1988-2008 Microsoft Corporation

    Developer Edition (64-bit) on Windows NT 6.0 <X64> (Build 6001: Service Pack 1)

    Do you have any explanation??

    Greets

    Flo

  • 15 seconds? Time for a new computer!

    --
    Adam Machanic
    whoisactive

  • Adam Machanic (4/27/2009)


    Adam Machanic (4/27/2009)


    Hmm, something you've changed is making your version an order of magnitude slower on my test system than either of my versions.

    OK, found it. Make your return type NVARCHAR(4000), not NVARCHAR(MAX). And while you're at it, ditch that _ syntax for locals, please for the love of readable code!!! 🙂

    😀

    I really like the _syntax to distinguish between local and module variables. Would you prefer m_anything? :laugh:

    Greets

    Flo

  • Adam Machanic (4/27/2009)


    15 seconds? Time for a new computer!

    I think Core2 Quad 2,4 is not so bad 😉

    All three methods use nvarchar(max). Copy paste error. Sorry again!

    Changed all to nvarchar(4000):

    Adadm1: 1220

    Adam2: 1160

    FR: 1210

    Greets

    Flo

  • Florian Reischl (4/27/2009)


    I really like the _syntax to distinguish between local and module variables. Would you prefer m_anything?

    Personally I like Pascal case for externally-facing variables and camel case for local and member variables. I didn't follow that standard too well in these examples but it's what I normally use and I find it to be quite nice for my purposes.

    Glad to hear you got the NVARCHAR issues sorted. I just load tested your mods to my original code and it looks like it's the current winner by a small margin.

    --
    Adam Machanic
    whoisactive

  • Hi Adam

    Adam Machanic (4/27/2009)


    Florian Reischl (4/27/2009)


    I really like the _syntax to distinguish between local and module variables. Would you prefer m_anything?

    Personally I like Pascal case for externally-facing variables and camel case for local and member variables. I didn't follow that standard too well in these examples but it's what I normally use and I find it to be quite nice for my purposes.

    Yeah, I also like the CamelCase! I use it for different words. I just distinguish between properties and public variables which start with an upper first character and local/module variables which start with a lower first character. I'm coming from the C/C++ side 😉

    Glad to hear you got the NVARCHAR issues sorted.

    Yepp!

    I just load tested your mods to my original code and it looks like it's the current winner by a small margin.

    I did not yet load tests but I have a new enumerator based solution which performs better than all the others on my system. Could you please try on your system?

    using System;

    using System.Collections;

    using System.Data;

    using System.Data.SqlClient;

    using System.Data.SqlTypes;

    using Microsoft.SqlServer.Server;

    public partial class UserDefinedFunctions

    {

    [Microsoft.SqlServer.Server.SqlFunction(

    FillRowMethodName="FillRow_SplitString_Enumerator_Flo2",

    TableDefinition="item nvarchar(4000)"

    )

    ]

    public static IEnumerator ufn_clr_SplitString_Enumerator_Flo2(

    [SqlFacet(

    IsFixedLength=false,

    IsNullable=false,

    MaxSize=-1

    )

    ]

    SqlChars strIn,

    [SqlFacet(

    IsFixedLength=false,

    IsNullable=false,

    MaxSize=255

    )

    ]

    SqlChars delimiter

    )

    {

    return new SplitStringEnumeratorFlo2(strIn.Value, delimiter.Value);

    }

    public static void FillRow_SplitString_Enumerator_Flo2(object obj, out SqlString item)

    {

    item = new SqlString((string)obj);

    }

    public class SplitStringEnumeratorFlo2 : IEnumerator

    {

    public SplitStringEnumeratorFlo2(char[] theString, char[] delimiter)

    {

    _theString = theString;

    _delimiter = delimiter;

    _delimiterLength = delimiter.Length;

    _lastPos = 0;

    _nextPos = _delimiterLength * -1;

    }

    #region IEnumerator Members

    public object Current

    {

    get

    {

    return new string(_theString, _lastPos, _nextPos - _lastPos);

    }

    }

    public bool MoveNext()

    {

    if (_nextPos >= _theString.Length)

    return false;

    else

    {

    _lastPos = _nextPos + _delimiterLength;

    for (int i = _lastPos; i _theString.Length)

    {

    return false;

    }

    else

    {

    bool matches = true;

    for (int j = 1; j < _delimiterLength; j++)

    {

    if (_theString != _delimiter[j])

    {

    matches = false;

    break;

    }

    }

    if (matches)

    {

    _nextPos = i + _delimiterLength;

    return true;

    }

    }

    }

    }

    _lastPos = _nextPos + _delimiterLength;

    _nextPos = _theString.Length;

    return true;

    }

    }

    public void Reset()

    {

    _lastPos = -1;

    _nextPos = -1;

    }

    #endregion

    private int _lastPos;

    private int _nextPos;

    private char[] _theString;

    private char[] _delimiter;

    private int _delimiterLength;

    }

    };

    For your test environment:

    --Flo2

    declare @d datetime

    set @d = getdate()

    select count(*) from #z

    cross apply dbo.ufn_clr_SplitString_Enumerator_Flo2(y, ',') q

    select datediff(ms, @d, getdate()) AS Flo2

    go

    Greets

    Flo

  • It does appear to be faster for a single delimiter, but it doesn't work properly for multiple delimiters:

    select * from dbo.ufn_clr_SplitString_Enumerator_Flo2('a,,b', ',,') q

    --
    Adam Machanic
    whoisactive

  • Bug in row 98... Thanks!

    Either replace:

    _nextPos = i + _delimiterLength;

    With:

    _nextPos = i; // +_delimiterLength;

    Or just copy paste the complete new:

    using System;

    using System.Collections;

    using System.Data;

    using System.Data.SqlClient;

    using System.Data.SqlTypes;

    using Microsoft.SqlServer.Server;

    public partial class UserDefinedFunctions

    {

    [Microsoft.SqlServer.Server.SqlFunction(

    FillRowMethodName="FillRow_SplitString_Enumerator_Flo2",

    TableDefinition="item nvarchar(4000)"

    )

    ]

    public static IEnumerator ufn_clr_SplitString_Enumerator_Flo2(

    [SqlFacet(

    IsFixedLength=false,

    IsNullable=false,

    MaxSize=-1

    )

    ]

    SqlChars strIn,

    [SqlFacet(

    IsFixedLength=false,

    IsNullable=false,

    MaxSize=255

    )

    ]

    SqlChars delimiter

    )

    {

    return new SplitStringEnumeratorFlo2(strIn.Value, delimiter.Value);

    }

    public static void FillRow_SplitString_Enumerator_Flo2(object obj, out SqlString item)

    {

    item = new SqlString((string)obj);

    }

    public class SplitStringEnumeratorFlo2 : IEnumerator

    {

    public SplitStringEnumeratorFlo2(char[] theString, char[] delimiter)

    {

    _theString = theString;

    _delimiter = delimiter;

    _delimiterLength = delimiter.Length;

    _lastPos = 0;

    _nextPos = _delimiterLength * -1;

    }

    #region IEnumerator Members

    public object Current

    {

    get

    {

    return new string(_theString, _lastPos, _nextPos - _lastPos);

    }

    }

    public bool MoveNext()

    {

    if (_nextPos >= _theString.Length)

    return false;

    else

    {

    _lastPos = _nextPos + _delimiterLength;

    for (int i = _lastPos; i _theString.Length)

    {

    return false;

    }

    else

    {

    bool matches = true;

    for (int j = 1; j < _delimiterLength; j++)

    {

    if (_theString != _delimiter[j])

    {

    matches = false;

    break;

    }

    }

    if (matches)

    {

    _nextPos = i; // +_delimiterLength;

    return true;

    }

    }

    }

    }

    _lastPos = _nextPos + _delimiterLength;

    _nextPos = _theString.Length;

    return true;

    }

    }

    public void Reset()

    {

    _lastPos = -1;

    _nextPos = -1;

    }

    #endregion

    private int _lastPos;

    private int _nextPos;

    private char[] _theString;

    private char[] _delimiter;

    private int _delimiterLength;

    }

    };

    Greets

    Flo

  • Can you please post the SQL build script for this CLR function, please. I'm stuck with my ...

    CREATE FUNCTION ....

    bit.

    ..and I bet most people who are trying to follow this lot are too!

    Best wishes,
    Phil Factor

  • Adam Machanic (4/27/2009)


    Hi all,

    I have posted a more scalable SQLCLR string split method here:

    http://sqlblog.com/blogs/adam_machanic/archive/2009/04/26/faster-more-scalable-sqlclr-string-splitting.aspx

    Thanks to Paul White for pointing me to this thread. Please consider testing all of these methods UNDER LOAD, using either SQLQueryStress, as I did, or another load tool. The results will be quite interesting, I promise. 😀

    I'm glad Paul pointed you here. I was planning on pointing Flo to your blog post if no one else had.

  • Jack Corbett (4/27/2009)


    Adam Machanic (4/27/2009)


    Hi all,

    I have posted a more scalable SQLCLR string split method here:

    http://sqlblog.com/blogs/adam_machanic/archive/2009/04/26/faster-more-scalable-sqlclr-string-splitting.aspx

    Thanks to Paul White for pointing me to this thread. Please consider testing all of these methods UNDER LOAD, using either SQLQueryStress, as I did, or another load tool. The results will be quite interesting, I promise. 😀

    I'm glad Paul pointed you here. I was planning on pointing Flo to your blog post if no one else had.

    Hi Jack

    Thank you! I'm also glad that this great CLR guy joined the discussion! His input was very important! The technical and the point that load tests are still missing.

    Greets

    Flo

  • Phil Factor (4/27/2009)


    Can you please post the SQL build script for this CLR function, please. I'm stuck with my ...

    CREATE FUNCTION ....

    bit.

    ..and I bet most people who are trying to follow this lot are too!

    Hi Phil

    Sorry, but I think I cannot. Currently I have only a x64 system. If you have a x64 system, sure!

    Greets

    Flo

Viewing 15 posts - 256 through 270 (of 522 total)

You must be logged in to reply to this topic. Login to reply