web-dev-qa-db-ja.com

クエリのCLR SQLとT-SQL

CLRストアドプロシージャは手続き型コードでより効率的であり、T-SQLはクエリに適していることを認識しています。ただし、特定のニーズに何を使用するかを決定するのに苦労しています。他に何かあるかどうか知りたいのですが。私の決断をするとき、私は考慮すべきです。

私が作成を計画しているコードには、一連のデータのクエリ、いくつかのアルゴリズムの実装(時間が経つにつれて複雑になる)、およびデータベースへのデータの挿入が含まれます。このストアドプロシージャは、スケジューラによってデプロイされます-私が知る限り、Azure SQLはdbジョブをサポートしていないため、おそらくAzure webJobsです。

C#を使用する理由

私は自分のサーバーからDALライブラリをロードでき、OOPを活用できると仮定します-この問題に対して、よりコーダーに優しいソリューションを実装できると思います-パフォーマンスに関しては、それがより良いか、少なくとも比較では目立ちません。

T-SQLを使用する理由

私は実際にはそれがより良い解決策であるとは信じていませんが、T-SQLの良いケースであると私が見落としていることがあるかもしれません。

最も重要

T-SQLストアドプロシージャを作成し、複雑なオブジェクトをパラメーターとして使用してC#ストアドプロシージャを呼び出す方法はありますか?アルゴリズムを実行して、挿入するデータを返し、T-SQLから挿入しますか?最もエレガントで最もパフォーマンスの高い(?)ソリューションのように見えます(それが可能であり、T-SQLからCLRを呼び出すことに欠点がないと仮定します)。

3
gilmishal

まず、明確にするために、SQLCLR/.NET/C#/ VB.NETはデータベースにクエリを実行できません。 T-SQLのみがSQL Serverにクエリを実行できます。したがって、SQLCLRコードでデータを取得したり、SQL Serverとやり取りしたりするには、他の.NETアプリと同様にSqlConnectionを確立し、T-SQLを送信するか、ストアドプロシージャを実行する必要があります。

はい、SQLCLR(C#でもVB.NETでもかまいません)ストアドプロシージャ、スカラー関数、またはテーブル値関数(TVF)などをT-SQLから呼び出すことができます。実際、それがSQLCLRオブジェクトを呼び出すことができる唯一の方法です。アセンブリで定義されたSQLCLRオブジェクトを表すクラスには、それらを呼び出すことができるように、それらのクラスを指すT-SQLラッパーオブジェクトが定義されている必要があります。

複雑なオブジェクトをSQLCLRオブジェクトに送信することはできますが、残念ながら、テーブル値パラメーター(TVP)を使用することはできません。ただし、T-SQLでローカル一時テーブルを作成してデータを入力し、SQLCLRオブジェクトでそのテーブルから選択することもできます。OR複雑なデータをXMLにパッケージ化して渡すことができます。 XmlReaderを介してトラバースするSQLCLRオブジェクトへのパラメーターとして。

データを効率的に戻すには、次のいずれかを実行できます。

  • SQLCLRストアドプロシージャからINSERTステートメントを発行する
  • TVPを受け入れるT-SQLストアドプロシージャを作成し、SQLCLRオブジェクトから呼び出します。
  • sQLCLRストアドプロシージャの場合はINSERT INTO ... EXEC、SQLCLR TVFの場合はINSERT INTO ... SELECTのように、INSERTステートメントで使用されるSQLCLRオブジェクトから結果セットを返します。

DALライブラリのロードに関する限り、couldは機能しますが、複雑になる可能性もあります。それはすべて、ライブラリが何をしているか、どのFrameworkライブラリが参照されているかによって異なります。小さな 。NET Frameworkライブラリのサブセット のみがSQL ServerのCLRホストでサポートされているため、ライブラリが「承認されていない」他のライブラリを参照している場合は、それらのライブラリを手動でロードする必要があります。依存しているライブラリのいずれか(ある場合)。ここでの複雑な要因は、サポートされていない.NET Frameworkライブラリをロードするには、それらをUNSAFEに設定する必要があり、そのため、データベースをTRUSTWORTHY ONに設定する必要があることです。 SQL Server内のCLRホストは純粋なMSILアセンブリのみを許可するため、.NET Frameworkライブラリをロードすることさえ不可能であることもあり、混合モードアセンブリをロードすることはできません。一部の.NET Frameworkライブラリは現在混合モードであり、ロードされません。その他は現在「純粋」でロードされますが、将来の.NET Frameworkの更新で混合モードアセンブリに変更されないguaranteeはありません。それが発生した場合(および System.ServiceModel などで発生した場合)、アセンブリを再コーディングする必要があります。したがって、サポートされているFrameworkライブラリは、将来のアップグレードでも引き続き機能することが保証されているため、そのまま使用することをお勧めします。

アプリドメインはデータベースごと、所有者ごと(アセンブリの)であることに注意してください。これは、特定のSQLCLRオブジェクトに関して、allセッション/ SPIDが同じコードを呼び出し、同じメモリを共有することを意味します。これが、メソッドをstaticとして宣言する必要がある理由です。そして、これがreadonly以外の静的クラス変数を使用しようとすると、アセンブリがUNSAFEとしてマークされる必要がある理由です。そのような変数の値は、別のセッション/ SPID(ケースポイント: SQLCLRアセンブリは、複数のクエリを同時に実行するとエラーをスローします )。

質問のこの声明に関して:

パフォーマンスに関しては、私はそれが比較して良いか、少なくとも目立たないと思います。

ここでは何も想定していません。どちらの方向でもパフォーマンスに影響を与える要因はたくさんあります。

  • 一部のデータ型は、SQL Serverメモリと.NET AppDomainメモリ間で他より高速に転送されます
  • c#でアルゴリズムをコーディングする方法(私は最近、LINQを使用する別の提案をすでに得ている人のために単純な関数を書きました-LINQバージョンは、私のバージョンが同じことをするのに375から400ミリ秒かかりました。完了するまでに2〜9ミリ秒、41倍から200倍の差!)
  • データの量(T-SQLは小さい値(通常は文字列)で高速になる場合がありますが、SQLCLRは長い値で高速になる場合があります)
  • あなたはベストプラクティスに従っていますか?確定的なSQLCLRスカラー関数をコーディングしていて、それをIsDeterministic=trueとしてマークしない場合、並列プランに参加できるという利点を得ることができません(T-SQL UDFが実行できないこと) )。

したがって、仮定しないでください。テスト!

SQLCLRの操作について詳しく知りたい場合は、SQL Server Centralでこのトピックについて書いているシリーズをチェックしてください。 SQLCLRへの階段 (アクセスするには無料登録が必要ですコンテンツ)。いくつかの記事などが続き、さまざまな機能やセキュリティなどを説明するための例がたくさんあります。


Azure SQLデータベースに関して:SQLCLR(SAFEアセンブリのみ)のサポートが2014年後半に追加されましたが、最近(そしておそらくtemporarily)に追加されました。削除されました。 2016年4月15日に削除される機能について、2016年4月8日にメールが送信されました。私が見つけた最も公式な通知は次のとおりです redditのスレッド

お客様:

Azure SQLでのCLRアセンブリのサポートはすぐに終了しますか?
この機能は4月15日以降はサポートされなくなる(!!!)というメールを(おそらく)今朝マイクロソフトから受け取ったので、これをお願いします。

Jan、a PMパフォーマンスとエラスティックプールに取り組んでいるAzure SQL DBチーム:

あなたが受け取った電子メールは確かに本物です。メールに記載されているように、SQLデータベースのユーザー定義のSQL CLRにはセキュリティリスクがあると判断しました。これまでに判明したエクスプロイトはありません。お客様のセキュリティを保護する取り組みの一環として、Azure SQLデータベースでのユーザー定義SQL CLRの使用を積極的に停止しました。つまり、ユーザー定義のSQL CLRは機能しなくなります。 6か月以内に、SQL CLRの復活のスケジュールをお知らせします。

およびTommy、a PM:

この問題はAzure SQL Databaseサービスにのみ適用され、オンプレミスのSQL ServerやIaaSには適用されません。

14
Solomon Rutzky