sql >> データベース >  >> RDS >> Database

STRING_SPLITの改善にご協力ください

    リリース間の中間サイクルであり、計画されている機能についてはまだ聞いていません。 SQLServervNext。正当なビジネスケースで要求を裏付けることができる限り、これはおそらくマイクロソフトに改善を求めるのに最適な時期です。 SQL Server 2016では、 STRING_SPLIT 確かに、複雑な文字列処理を目的としていない言語の長い間欠けていたギャップを解決しました。そして、それが今日私が提起したいことです。

    SQL Server 2016の前の数年間(およびそれ以降の数年間)、私たちは独自のバージョンを作成し、時間の経過とともにそれらを改善し、誰が最速であるかについてさえ議論してきました。私たちは得ることができるすべてのマイクロ秒についてブログを書きました、そして私は、例えば、「これは文字列の分割についての私の最後の投稿です!」と何度も述べました。まだここにいます。

    私は常に、テーブル値のパラメーターが文字列を分解する正しい方法であると主張します。しかし、 これらのカンマ区切りのテキストの塊は、その形式でデータベースに公開されるべきではないと考えています。文字列の分割は引き続き一般的なユースケースです。ここにある私のブログ投稿のいくつかは、ビューのトップ5にあります毎日

    では、優れた置換が存在するのに、なぜ人々はまだテーブル値関数で文字列を分割しようとしているのでしょうか? TVPが言語やORMでサポートされていないために、古いバージョンのままであるか、古い互換性レベルでスタックしている、または文字列の分割から逃れることができないため、確かにいくつかあります。残りの部分については、 STRING_SPLIT 便利で効率的ですが、完璧ではありません。多少の摩擦があり、既存の関数呼び出しをネイティブ呼び出しに置き換えるのが面倒または不可能になるという制限があります。

    これが私のリストです。

    これらの制限は完全ではありませんが、重要な制限を myにリストしました。 優先順位(そして今日もアンディ・マロンがこれについてブログに書いています):

    • 1文字の区切り文字
      この関数は、CSVという非常に単純なユースケースのみを念頭に置いて作成されたようです。人々は1,2,3よりも複雑な文字列を持っています またはA| B | C 、そしてそれらはしばしば彼らの制御外のシステムから彼らのデータベースに供給されます。この回答とこのヒントで説明しているように、これを回避する方法はありますが(実際には非効率的な置換操作)、それらは本当に醜く、率直に言って、ネイティブ実装によって提供されるすべてのパフォーマンス上の利点を元に戻します。また、これとの摩擦の一部は、具体的には次のようになります。「まあ、PostgreSQLの string_to_array 複数の文字区切り文字を処理するのに、SQL Serverができないのはなぜですか? "実装: Separatorの最大サイズを増やしてください 。
    • 入力順序の表示なし
      関数の出力はセットであり、本質的にセットには順序がありません。ほとんどの場合、 bob、ted、frankのような入力文字列が表示されます。 この順序で出てきます( bob ted フランク )、保証はありません(ずさんな(ORDER BY(SELECT NULL))の有無にかかわらず ハック)。多くの自家製関数には、文字列内の順序位置を示す出力列が含まれています。これは、リストが定義された順序で配置されている場合、または正確な順序位置に何らかの重要性がある場合に重要になる可能性があります。実装:順序位置列を含めるオプションを追加します。出力。
    • 出力タイプは入力のみに基づいています
      関数の出力列はvarcharのいずれかに固定されています またはnvarchar 、およびは、最長の要素の長さではなく、入力文字列全体の長さによって正確に決定されます。したがって、25文字のリストがあり、出力タイプは少なくともです。 varchar(51) 。より長い文字列の場合、これは使用法に応じてメモリ付与の問題に細流化する可能性があり、コンシューマーが出力されている別のデータ型(たとえば、 int )に依存している場合に問題を引き起こす可能性があります 、関数は後で暗黙の変換を回避するために指定することがあります)。回避策として、ユーザーが独自の一時テーブルまたはテーブル変数を作成し、関数を操作する前にそこに関数の出力をダンプすることがあります。これにより、パフォーマンスの問題が発生する可能性があります。実装:valueの出力タイプを指定するオプションを追加します。
    • 空の要素または末尾の区切り文字を無視することはできません
      a ,,, b、のような文字列がある場合 、他の3つは空であるため、2つの要素のみが出力されると予想される場合があります。私が見たほとんどのカスタムTVFは、末尾の区切り文字を削除したり、長さがゼロの文字列を除外したりしますが、 STRING_SPLIT 5行すべてを返します。これにより、これらのエンティティを削除するためにラッピングロジックも追加する必要があるため、ネイティブ関数でのスワップが困難になります。実装:空の要素を無視するオプションを追加します。
    • 重複をフィルタリングできません
      これはおそらくあまり一般的ではないリクエストであり、 DISTINCTを使用して簡単に解決できます またはGROUPBY 、しかし、多くの関数がこれを自動的に行います。これらの場合、パフォーマンスに実際の違いはありませんが、自分で追加するのを忘れた場合があります(重複が多い大きなリストを考えて、大きなテーブルに結合します)。

      実装:重複を除外するオプションを追加します。

    これがビジネスケースです。

    これらはすべて理論的に聞こえますが、これがビジネスケースであり、非常に現実的であると確信できます。 Wayfairには、かなりのSQL Serverの資産があり、文字通り何十もの異なるチームが、長年にわたって独自のテーブル値関数を作成してきました。他のものより優れているものもありますが、それらはすべて数千行のコードから呼び出されます。最近、それらを STRING_SPLITの呼び出しに置き換えようとしているプロジェクトを開始しました 、しかしブロックケースに遭遇しました 上記の制限のいくつかを含みます。

    ラッパー関数を使用すると、簡単に回避できるものもあります。ただし、単一文字の区切り文字 制限により、 REPLACEを使用してひどい回避策を評価する必要がありました 、そしてこれは私たちが期待していたパフォーマンス上の利点を排除し、ブレーキをかけるようにすることを証明しました。そして、そのような場合、互換性レベルへのアップグレードを推進する際に重要な交渉チップを失いました(すべてのデータベースが130にあるわけではなく、140を気にする必要はありません)。そのような場合、 STRING_SPLITだけでなく負けています。 改善だけでなく、 STRING_SPLIT の場合、他の130以上のパフォーマンスの改善も享受できます。 互換性レベルのアップグレードを推進するために、それ自体で十分に説得力がありました。

    それで、私はあなたの助けを求めています。

    このフィードバック項目にアクセスしてください:

    • STRING_SPLITは完全な機能ではありません

    投票してください! さらに重要なのは、コメントを残す STRING_SPLITを作成する実際のユースケースを説明する あなたにとっての苦痛または非スターター。投票だけでは十分ではありませんが、十分な具体的かつ定性的なフィードバックがあれば、これらのギャップを真剣に受け止め始める可能性があります。

    複数文字の区切り文字をサポートしたいと思います(たとえば、 [n] varchar(1)から拡張した場合でも [n] varchar(5)へ )は、私のシナリオを共有する多くの人々のブロックを解除する、邪魔にならない改善です。他の拡張機能は実装が難しい場合があり、オーバーロードや言語拡張機能が必要なものもあるため、vNextでこれらの修正がすべて行われるとは思いません。ただし、わずかな改善が1つでも、 STRING_SPLITを繰り返すことになります。 価値のある投資であり、放棄されることはありません(たとえば、最も有名なドライブバイ機能の1つであるデータベースが含まれています)。

    聞いてくれてありがとう!


    1. Docker、Java Spring、JDBCを使用したMariaDBの使用開始

    2. 'Order by'が指定されていない場合、クエリはレコードセットに対してどの順序を選択しますか?

    3. ODBCはどれくらい速いですか? 「ロードされた」比較。

    4. AWS RDS:「SQLSTATE [22001] –データが列に対して長すぎます」MariaDB10.2を使用