web-dev-qa-db-ja.com

SqlDependencyの制限は何ですか

テーブルをメッセージキューとして使用し、SqlDependencyを使用して更新プログラムに "サインアップ"しています。私が読むどこでも、人々はそれの限界に目を向けると言っているが、彼らが何であるかを具体的に言っているわけではない。私が収集したものから、テーブルの更新頻度が非常に高い場合に問題が発生します。幸いなことに、最大で毎分10〜20の値しか見ていません。

SqlServerの他の制限/影響は何ですか?

40
fluf

私が見つけることができる最も完全なリスト( ここから )は次のとおりです。

  • SELECTステートメントの投影列は明示的に指定する必要があり、テーブル名は2部構成の名前で修飾する必要があります。これは、ステートメントで参照されるすべてのテーブルが同じデータベースに存在する必要があることを意味することに注意してください。
  • このステートメントでは、アスタリスク()またはtable_name。構文を使用して列を指定することはできません。
  • このステートメントでは、名前のない列または列名の重複を使用できません。
  • ステートメントはベーステーブルを参照する必要があります。
  • ステートメントは、計算列を持つテーブルを参照してはなりません。
  • SELECTステートメントの投影された列には、ステートメントがGROUP BY式を使用しない限り、集計式を含めることはできません。 GROUP BY式が指定されている場合、選択リストには集計関数COUNT_BIG()またはSUM()が含まれている場合があります。ただし、SUM()はNULL可能列には指定できません。このステートメントでは、HAVING、CUBE、またはROLLUPを指定できません。
  • 単純式として使用されるSELECTステートメント内の投影された列は、複数回出現してはなりません。
  • ステートメントにPIVOTまたはUNPIVOT演算子を含めることはできません。
  • ステートメントには、UNION、INTERSECT、またはEXCEPT演算子を含めることはできません。
  • ステートメントはビューを参照してはなりません。
  • ステートメントには、DISTINCT、COMPUTEまたはCOMPUTE BY、INTOのいずれも含めることはできません。
  • このステートメントは、サーバーのグローバル変数(@@ variable_name)を参照してはなりません。
  • ステートメントは、派生テーブル、一時テーブル、またはテーブル変数を参照してはなりません。
  • このステートメントは、他のデータベースまたはサーバーのテーブルまたはビューを参照してはなりません。
  • ステートメントには、サブクエリ、外部結合、または自己結合を含めることはできません。
  • ステートメントは、ラージオブジェクトタイプ(text、ntext、およびimage)を参照してはなりません。
  • このステートメントでは、CONTAINSまたはFREETEXTフルテキスト述語を使用しないでください。
  • このステートメントでは、OPENROWSETやOPENQUERYなどの行セット関数を使用しないでください。
  • ステートメントは、AVG、COUNT(*)、MAX、MIN、STDEV、STDEVP、VAR、またはVARPの集約関数を使用してはなりません。
  • このステートメントでは、ランキング関数やウィンドウ関数などの非決定的な関数を使用しないでください。
  • ステートメントには、ユーザー定義の集計を含めることはできません。
  • このステートメントは、カタログビューや動的管理ビューなどのシステムテーブルまたはビューを参照してはなりません。
  • ステートメントにFOR BROWSE情報を含めることはできません。
  • ステートメントはキューを参照してはなりません。
  • ステートメントには、変更できず、結果を返すことができない条件ステートメントを含めることはできません(たとえば、WHERE 1 = 0)。
  • このステートメントでは、READPASTロックヒントを指定できません。
  • このステートメントは、Service Broker QUEUEを参照してはなりません。
  • ステートメントは同義語を参照してはなりません。
  • ステートメントには、double/realデータ型に基づく比較または式を含めることはできません。
  • このステートメントでは、TOP式を使用しないでください。

追加の参照:

61
Smudge202

これに加えて、SqlDependencyを使用して変更に関する通知を受け取ることを考えている人のために、私は本番環境でこのアプローチを使用しており、問題を見つけています。問題がコードに関連しているかどうかを確認するために調べていますが、主な問題は次のとおりです。

  • 複数の変更をすばやく連続して実行する場合、常に同じ数のイベントがコードに到達するとは限りません。私のコードでは、2つの新しいレコードが次々に挿入されると、1つの通知のみを受け取ります(最後の通知)。

  • 追加されたレコードを知る方法はありません。したがって、新しいレコードを追加し、通知を受信するためにコードが起動した場合、コードにはその新しいレコードのIDを知る方法がないため、データベースにクエリを実行する必要があります。

12
Matt Roberts

SQL Service Brokerが機能しない問題を追跡するために1日を費やしました。根本的な原因は、ストアドプロシージャでデータベースを参照していました。

たとえば、次のselectはSQL Management Studioで正常に機能します。

select [MyColumn] from [MyDatabase].[MySchema].[MyTable]

ただし、これはselectステートメントでデータベースを参照しているため、SQLサービスブローカーによって拒否され、SqlDependencyからのコールバックはSqlNotificationEventArgs eInvalidで返されます。 http://msdn.Microsoft.com/en-us/library/ms189308.aspx

SqlDependencyに渡されるSQLを次のステートメントに変更すると、エラーがなくなりました。

select [MyColumn] from [MySchema].[MyTable]

更新

上記の例は、SQL Service Brokerが依存するSQLステートメントに対する多くの制限の1つにすぎません。制限の完全なリストについては、 SqlDependency の制限を参照してください。

理由? SQL Service Brokerが使用するSQLステートメントは、舞台裏でデータベースへの変更について SQLトランザクションログ を監視する指示に変換されます。この監視はSQL Serverのコアで実行されるため、テーブルの変更を検出する際に非常に高速になります。ただし、この速度にはコストがかかります。SQLステートメントのみを使用することはできません。命令に変換できるステートメントを使用して、 SQLトランザクションログを監視する必要があります

9
Contango

ストアドプロシージャでnolockヒントを使用することはできません。使用しないと、依存関係は常に無効なままであるため、作成したキャッシュは永続的にデータベースを再クエリします。

with (NOLOCK) 

これはドキュメントで言及されていないようです(私が知る限り)

手続きスクリプトの前に、次のSETオプションが必要です。

SET ANSI_NULLS ON
SET ANSI_PADDING ON  
SET ANSI_WARNINGS ON

他の人は、これらのSETオプションも必要であると主張しましたが、そうではないと思います。とにかくこのように設定することをお勧めします。

SET CONCAT_NULL_YIELDS_NULL ON 
SET QUOTED_IDENTIFIER ON 
SET NUMERIC_ROUNDABORT OFF 
SET ARITHABORT ON
5
David Bridge

このテクノロジーに関するもう1つの大きな問題は、サブスクライバー接続にCreate Procedureアクセス許可が必要なことです。現在作業中のアプリケーションのWebサービスレイヤーは、制限付きユーザーとして実行されます。 SQLDependencyを使用して通知セットアップを取得するには、そのユーザーを開いてprocを作成する必要があります。所有権を取得する道に沿って、かなり良いステップのように思えます。

3
Mike

これらの制限を克服するには、SqlTableDependencyを使用してみてください。 www.sqltabledependency.itをご覧ください

Service Brokerを使用します。したがって、管理されていないSQL Azureインスタンスでは機能しません。したがって、SQL Azureを使用している場合、または使用している場合は注意してください。

https://docs.Microsoft.com/en-us/Azure/sql-database/sql-database-features

サービスブローカー

単一のデータベースとエラスティックプールでサポート:

番号

マネージドインスタンスでサポート:

はい、ただしインスタンス内のみ。 Service Brokerの違い を参照してください

すべての環境で使用できない限り、おそらく適切ではありません!

0
Simon_Weaver