DBテーブルでのSPIDの使用(テーブル変数の代わり)


8

予約に使用されるトランザクションデータベース...

私たちのベンダーは、#temptablesを@tablevariablesに置き換えるように依頼されました(コンパイルロックが重いため)。代わりに、SPIDを列として追加する実際のテーブルに置き換えて、ストアドプロシージャが適切な行でのみ機能するようにしました。

この操作方法にリスクはありますか?すべてのトランザクションが独自のトランザクション内に分離される前に...このテーブルを大量にロックしてしまうのではないかと心配しましたが、SQLは行レベルのロックを使用しているため、これ以上のロックは作成されないというのが彼らの意見です。

SQL Serverバージョン:2016 Enterprise-13.0.5216.0


CREATE TABLE dbo.qryTransactions (
    ID int IDENTITY (0,1) NOT NULL CONSTRAINT pk_qryTransactions PRIMARY KEY CLUSTERED,
    spid int NOT NULL,
    OrderID int,
    ItemID int,
    TimeTransactionStart datetime,
    TimeTransactionEnd datetime,
...other fields
    )

CREATE INDEX idx_qryTransactions_spidID ON qryTransactions (spid, ID) INCLUDE (ItemID, OrderID, TimeTransactionStart, TimeTransactionEnd)

1
場合によります。テーブルを同時に使用しているセッションの数、セッションのアクティブ度、テーブル内のレコードの数、この新しいテーブルのレコードは削除されるか、または残りますか?5セッション、大したことはありません。500セッション、各セッションのローカルな一時テーブル/変数では見えないブロッキングが発生する可能性が高いです。
John Eisbrener、

どのバージョンのSQLサーバーを使用していますか?
Anthony Genovese

2016 Enterprise-13.0.5216.0
アウトジェット

テーブルをヒットするセッションあたりのレコード数は1〜50です...それらは削除されるため、そのテーブル自体は一度に1,000行を超えることはおそらくありません...同時セッションはおそらく50程度でしょう...
outjet

1
このパスを強制的に下がる場合は(避けてください)、spid値のパーティション分割を真剣に検討して、テーブルのロックエスカレーションがAUTOに設定されていることを確認します。次に、少なくとも特定のspidのデータのワイプをスイッチと切り捨て操作で実行できます。
ジョナサンファイト

回答:


5

コメントブロックに収まりきらないほど少しまとまっていて、レイの答えに応じてOPが作成したコメントを強調したい場合:

  • 親プロシージャ(Common_InsertOrders_1)は一時テーブルを作成します
  • 子プロシージャ(InsertOrders)は一時テーブルをクエリします
  • 子プロシージャ(InsertOrders)のコンパイルロックが表示されている

1分間少し接していきます...このシナリオで何が起こるかについてはSybase ASEです...

  • 各一時テーブルは一意のオブジェクトIDを取得します(確かに、オブジェクトIDはいつか再利用できますが、これはまれであり、同時セッションでは発生しません)。
  • 一時テーブルのオブジェクトID が変更されたため、Sybase ASEは通常、子プロシージャの実行ごとに強制的に再コンパイルします。
  • また、Sybase ASEは、ストアドプロシージャの呼び出し間で一時テーブルの構造が変更された(列の数、列名/データ型/ null可能性など)と判断した場合、子procの再コンパイルを強制します。
  • より最近のバージョンのSybase ASEには、一時テーブルオブジェクトIDの変更を無視するように(事実上)コンパイラーに指示する構成があるため、子プロシージャの再コンパイルは不要です(注:テーブル構造が変更された場合でも、再コンパイルは発生します)。

OPの問題に戻ります(子プロシージャのコンパイルロック)...

  • Sybase ASEの動作の一部がSQL Serverに残っている可能性はありますか(2つの製品がポッドでエンドウ豆だったときから)。
  • (オブジェクトIDの変更が原因で)子プロシージャの再コンパイルを削減(排除)できるSQL Server構成はありますか?
  • OPは、親プロシージャが毎回同じ正確な構造/ DDLで一時テーブルを作成していることを確認できますか?

セッション間で行を区別するために@@ SPIDで単一の永続テーブルを使用するという考えについては...そこにあります... 残念です。繰り返し発生する問題:

  • 孤立した行をクリーンアップする方法とタイミング
  • データベースエンジンが@@ SPIDを再利用すると、孤立したデータが存在する場合(または孤立したデータのクリーンアップ中に@@ SPID = 10が削除されるが、@で新しい/現在/アクティブなセッションがある場合など)、データの正確性の問題が発生する可能性があります。 @ SPID = 10 =>クリーンアップが削除するデータが多すぎます)
  • 行ロックからページ/テーブルロックへのロックエスカレーションの可能性
  • テーブルにインデックスがある場合、インデックスの更新時に潜在的な(b)ロック
  • テーブルが存在するデータベースに応じて、ログデバイスに書き込むためのより多くのアクティビティを確認している可能性があります(Sybase ASEでは、tempdbでのログ記録を効果的に無効にすることができます)。
  • 行レベル(排他的)のロックでさえ、他のセッションをブロックする可能性があります(分離レベルと、セッションが上記の排他的ロックをスキャンアンドペースト/スキップできるかどうかによって異なります)。

私は戻って根本的な問題(子プロシージャの再コンパイルロック)を(再)調査し、上記のコンパイルロックを削減(排除?)する方法があるかどうかを確認したいと思います。[残念ながら、これらの問題に関する私のSQL Serverの知識は... NULL ...なので、SQL Serverコンパイラの専門家からの入力に興味があります。]


1
同意します。コンパイルロックの調査にもっと時間をかける必要があると思います。これには、調査すべきいくつかのポイントがあります。 support.microsoft.com/en-us/help/263889/...
ジョナサンFITE

8

@@SPID困るような使い方をしてるようです。

セッションIDは頻繁に再利用されます。ユーザー接続がログアウトするとすぐに、そのセッションIDは再び使用できるようになり、接続を試みる次のセッションで使用される可能性があります。

少なくともある程度の信頼性で機能させるには、同じを使用してテーブルから前の行を削除するログイントリガーが必要@@SPIDです。これを行うと、@@SPID列を使用してテーブルが大量にロックされる可能性があります。

SQL Serverは実際に行ロックを使用しますが、ページロックとテーブルロックも使用します。もちろん、適切なインデックス付けによってそれを軽減できるかもしれませんが、これはまだ私にはアンチパターンのように見えます。

ストアドプロシージャが影響を受けるテーブルへのアクセスに使用される唯一の方法である場合sp_getapplock、関連する部分へのアクセスを基本的にシリアル化するために、アプリケーションロックを使用して調査できます。sp_getapplockのドキュメントはこちらです。 Erik Darlingが興味深い投稿をしています


4

はい、リスクはあります。行ロックを使用してSQLを信頼するのは簡単です。たとえば、挿入と削除では少なくともページロックを使用すると確信しています。SQLエンジンは、いくつかの要因に基づいてロックの種類を選択しますが、これらの要因には「自分の意見」は含まれません。一時テーブルをテーブル変数に変更するような包括的なソリューションは、一般的にも悪い考えです。テーブル変数は状況によっては非常に役立ちますが、制限とパフォーマンスの問題があります。私はほとんどの状況で一時テーブルを好みます。特に、テーブルが数十行を超える場合。システムに「重いコンパイルロック」が発生した理由と、それによってパフォーマンスがどのように低下​​したかをベンダーに説明する必要があります。あなたが見ているときはいつでも、あなたはある種の「重いロック」を見つけるでしょう。それは必ずしもロックが問題であることを意味しません。マックス @@ SPIDに関するコメントも重要です。さらに、トランザクションモデルとエラー処理は大きな問題になる可能性があります。システムでデッドロックまたは入力データ品質の問題が発生した場合、標準エラー処理により、qryTransactionsテーブルが適切にリセットされずにセッションが終了する可能性があります。IMOは、元の問題に対する間違ったソリューションアプローチです。


答えてくれてありがとう-要点:トレースは、ストアドプロシージャInsertOrdersのコンパイルロックをLCKが大量に待機していることを示しています。一時テーブル#qryTransactionsを宣言する親プロシージャCommon_InsertOrders_1があり、次にネストされたプロシージャInsertOrders_2が一時テーブルをクエリします。また、私たちは、空の一時テーブルに6修正した後、任意のストアドプロシージャが一時テーブルを再コンパイルする必要がありますことを参照するため、頻繁に再コンパイルもあります学んだ
outjet

プロシージャまたはステートメントが再コンパイルされる理由は多数あります。MarkPはSyBaseに適用されるそれらの多くに言及しており、SQL Serverも同様であると確信しています。一時テーブルの行数は良い例であり、再コンパイルは必ずしも悪いことではありません。テーブル統計は最適なクエリプランを大幅に変更する可能性があり、それを決定するには再コンパイルが必要です。しかし、繰り返し述べたいと思います。常に上部ロックがあり、それはロックが問題であることを意味しません。パフォーマンスの問題に関する他の証拠が見られない限り、心配する必要はありません。
レイ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.