19

可能な限り最善の方法でテーブルにスワップしたい。
IpToCountry テーブルがあり、インポートした外部 CSV ファイルに従って毎週新しいテーブルを作成しています。

切り替えを行うために私が見つけた最速の方法は、次のことでした。

sp_rename IpToCountry IpToCountryOld
go
sp_rename IpToCountryNew IpToCountry
go

これに関する問題は、その間にテーブルがまだアクセスされる可能性があることです。
SQL でこの問題に取り組むにはどうすればよいですか?
sp_getapplock と sp_releaseapplock を使用することを検討しましたが、テーブル関数からの読み取りをできるだけ高速に保ちたいと考えています。

4

6 に答える 6

17

既存のテーブルに更新/挿入できないと仮定すると、ビューを使用してテーブルへのすべてのアクセスをラップしてみませんか?

たとえば、最初にデータをIpToCountry20090303というテーブルに格納すると、ビューは次のようになります。

CREATE VIEW IpToCountry
AS
SELECT * FROM IpToCountry20090303

新しいデータが入ってきたら、IpToCountry20090310テーブルを作成して入力できます。テーブルにデータが入力されたら、ビューを更新するだけです:

ALTER VIEW IpToCountry
AS
SELECT * FROM IpToCountry20090310

切り替えは完全にアトミックであり、明示的なロックやトランザクションは必要ありません。ビューが更新されたら、古いテーブルを単純に削除できます (または、必要に応じて保持します)。

于 2009-03-03T11:36:40.213 に答える
3

パーティショニング関数を大規模に機能させるのに問題がありました。CREATE と DROP PARTITION はブロッキング操作であり、ブロッキングをほとんど制御できません。ロックを取得できない場合、重大度レベル 16 で失敗し、接続を切断します。これをトラップして再確立せずに再試行することはできません。接続。しかし、それはあなたにとってうまくいくかもしれません。また、MSS Enterprise Edition が必要です。SE を使用することはできません。小規模なショップやコストを重視するショップにとっては多すぎる可能性があります。

また、ビューの再定義が sys テーブルとオブジェクトで大規模 (= トランザクション ボリューム + 常に挿入される膨大な量のデータ) でブロックされることも発見しました。あるケースでは、特に SSMS の (すべての) ユーザーがオブジェクト エクスプローラーでビューを参照しようとしています (誰かが READPAST についてそれらの人に伝える必要があります)。繰り返しますが、走行距離は異なる場合があります。

対照的に、sp_rename は大規模にうまく機能します。これにより、ロックとその範囲を制御できます。スワップ前にブロックの問題を解決するには、以下に示すように試してください。額面どおり、これは大容量で同じ規模の問題を抱えているように見えますが、実際には見たことがありません。だから、私にはうまくいきます... しかし、繰り返しになりますが、ニーズや経験は人それぞれ異なります。

DECLARE @dummylock bit 
BEGIN TRANSACTION 
BEGIN TRY
   -- necessary to obtain exclusive lock on the table prior to swapping
   SELECT @dummylock = 1 WHERE EXISTS (SELECT 1 FROM A WITH (TABLOCKX))
   -- may or may not be necessary in your case
   SELECT @dummylock = 1 WHERE EXISTS (SELECT 1 FROM B WITH (TABLOCKX))
   exec sp_rename 'A', 'TEMP'
   exec sp_rename 'B', 'A'
   exec sp_rename 'TEMP', 'B'
   COMMIT TRANSACTION
END TRY
BEGIN CATCH
   -- other error handling here if needed
   ROLLBACK TRANSACTION 
END CATCH
于 2011-03-11T15:53:42.240 に答える
1

達成しようとしていることを実装する別の方法は、SQLServerのEnterpriseEditionで使用できる手法であるテーブルパーティションの使用です。

テーブル名は同じままにすることができます。テーブルのインポートが完了したら、古いデータを含むパーティションを切り替えて、新しいパーティションに切り替えるだけです。

次のホワイトペーパーには、開始するために必要なすべての情報が含まれています。

http://msdn.microsoft.com/en-us/library/ms345146.aspx

乾杯、ジョン

于 2009-03-03T12:34:22.100 に答える
0

IpToCountryOld はどうなりますか? 捨てますか?その場合、IpToCountry を切り捨てて新しいデータをインポートしてみませんか。

データを保持する必要がある場合は、ロード日をテーブルに保存し、「現在の」ロード日をどこかに保存して WHERE 句で使用するのはどうですか? 次に、データが正常に読み込まれた時点で現在の日付を切り替えます。

どのDBを使っているかは書かれていないので、どれくらいの使用量かわかりませんが、テーブルを参照するストアドプロシージャはありますか?一部のプラットフォームでは、名前を変更しても変更されないテーブルへの内部参照を使用して SP がコンパイルされるため、再コンパイルしないと SP が新しいデータを取得できないリスクがあることに注意してください。ビューと保存された解析済みクエリについても同じことが言えます。

于 2009-03-03T09:57:33.383 に答える
0

営業時間外にワンテーブルへのインポートはできませんか?

または、単にデータを更新しないでください。つまり、既存のレコードを更新し、データをインポートするためにループするときにレコードごとに新しいレコードを追加します。これにより、テーブルをライブのままにし、完全なテーブルを追加および削除することによる全体的な影響を軽減できます。

インポートされるデータの構造、テーブルの設計、フォーマット、PK などは? そこから、より良い答えを提供できるかもしれません。

于 2009-03-03T10:31:29.527 に答える
0

適切なロックでのスケーリングに問題があるステージング テーブルで同様の問題が発生しました。

テーブルが参照される場所ならどこでも、テーブル名を要求するストアド プロシージャを呼び出すことができます。

ストアド プロシージャは、指定されたパラメーターに応じて、オプションで新しいテーブルを作成するか、古いテーブルを返します。

于 2013-04-13T19:47:37.693 に答える