先週の私の投稿に続いて、文字列の分割について多くのコメントがありました。この記事のポイントは、それほど明白ではなかったと思います。T-SQLに基づく本質的に遅い分割関数を「完成」させるために多くの時間と労力を費やすことは、有益ではないということです。それ以来、Jeff Modenの文字列分割関数の最新バージョンを収集し、他のバージョンと比較しました。
ALTER FUNCTION [dbo].[DelimitedSplitN4K] (@pString NVARCHAR(4000), @pDelimiter NCHAR(1)) RETURNS TABLE WITH SCHEMABINDING AS RETURN WITH E1(N) AS ( SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 ), E2(N) AS (SELECT 1 FROM E1 a, E1 b), E4(N) AS (SELECT 1 FROM E2 a, E2 b), cteTally(N) AS (SELECT TOP (ISNULL(DATALENGTH(@pString)/2,0)) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4), cteStart(N1) AS (SELECT 1 UNION ALL SELECT t.N+1 FROM cteTally t WHERE SUBSTRING(@pString,t.N,1) = @pDelimiter ), cteLen(N1,L1) AS(SELECT s.N1, ISNULL(NULLIF(CHARINDEX(@pDelimiter,@pString,s.N1),0)-s.N1,4000) FROM cteStart s ) SELECT ItemNumber = ROW_NUMBER() OVER(ORDER BY l.N1), Item = SUBSTRING(@pString, l.N1, l.L1) FROM cteLen l; GO
(私が行った唯一の変更:表示用にフォーマットし、コメントを削除しました。元のソースはここで取得できます。)
ジェフの機能を公正に表すために、テストにいくつかの調整を加える必要がありました。最も重要なこと:4,000文字を超える文字列を含むすべてのサンプルを破棄する必要がありました。そこで、dbo.stringsテーブルの5,000文字の文字列を4,000文字に変更し、最初の3つの非MAXシナリオのみに焦点を当てました(最初の2つのシナリオでは以前の結果を保持し、新しいシナリオでは3番目のテストを再度実行します) 4,000文字の文字列の長さ)。また、1つを除くすべてのテストからNumbersテーブルを削除しました。これは、パフォーマンスが常に少なくとも10倍悪化することが明らかだったためです。次のグラフは、4つのテストのそれぞれにおける関数のパフォーマンスを示しています。平均して10回以上実行され、常にコールドキャッシュとクリーンバッファが使用されます。
ですから、タスクの種類ごとに、少し修正した推奨方法を次に示します。
分割が意味をなさない1つの場合を除いて、CLRが私の選択の方法であり続けていることに気付くでしょう。また、CLRがオプションではない場合、Jeffの関数が最適なオプションである可能性がある単一変数分割の場合を除いて、XMLおよびCTEメソッドは一般により効率的です。ただし、4,000文字を超える文字をサポートする必要がある場合は、CLRの使用が許可されていない特定の状況で、Numbersテーブルソリューションがリストに戻る可能性があります。
リストに関する次の投稿では、T-SQLまたはCLRを介した分割についてはまったく説明せず、データ型に関係なくこの問題を単純化する方法を示すことを約束します。
余談ですが、コメントに投稿されたジェフの関数のバージョンの1つで、このコメントに気づきました。次のURLにある「数値テーブル」とアダムマハニックに最初に見た記事を書いた人にも感謝します。何年も前に私を導いてくれてありがとう。http://web.archive.org/web/20150411042510/http://sqlserver2000.databases.aspfaq.com/why-should-i-consider-using-an -auxiliary-numbers-table.html
その記事は、2004年に私が書いたものです。したがって、関数にコメントを追加した人は誰でも歓迎します。 :-)