2017-12-24 55 views
2

私はイベントを格納するためにC#でSQLデータベースを使用しています。私のテーブル名はTabOfEventsです。それはイベントのコードとこのイベントの日時を持っています。SQLデータベースの行数を制限し、限界に達したときに行を上書きする方法は?

CREATE TABLE [dbo].[TabOfEvents] (
    [Id] INT IDENTITY (1, 1) NOT NULL, 
    [cta] NCHAR (10) NOT NULL, 
    [code] NVARCHAR (MAX) NOT NULL, 
    [date] DATETIME2 (7) NULL, 
    PRIMARY KEY CLUSTERED ([Id] ASC) 
) 

イベントが発生するたびに、日付(最新のものから古いもの)順に並べ替えてテーブルに保存します。

私のデータベースの行数を100,000行(たとえば、300Moと言っていますが、可能ならばこれについてはわかりません)と制限数私は最も古いイベントを上書きし、新しいイベントで置き換えたいと考えています。

C#でどうすればいいですか?

答えて

0

ring bufferとして使用される表のポインタにCYCLEオプションが使用されたsequenceを使用できます。これは、データベース内のシーケンスオブジェクトを作成します。

CREATE SEQUENCE BufferPtr 
    START WITH 1 
    MINVALUE 1 
    MAXVALUE 100000 
    CYCLE; 

は空のエントリを許可するとID

CREATE TABLE dbo.TabOfEvents (
    [Id] INT NOT NULL, 
    [cta] NCHAR (10) NULL, 
    [code] NVARCHAR (MAX) NULL, 
    [date] DATETIME2 (7) NULL, 
    PRIMARY KEY CLUSTERED ([Id] ASC) 
) 

が続い100000枚の空のレコードとIDが1でテーブルを埋める入力できるように、異なるテーブルを作成します。.. 100000私たちは事前にレコード数を知り、自分自身でクエリを保存するためにこれを行います。つまり、挿入または更新を行う必要があるかどうかを知るために、レコードの数をSELECT COUNT (*) FROM TabOfEventsと照会する必要はありません。 Sequenceは、更新するレコードを決定するためにUPDATEコマンド自体で使用されます。新しいシーケンス番号が毎回生成され、上限10万に達した後のシーケンスは、今1

-- This creates 100000 empty records with an Id. The code is quite tricky and I won't explain 
-- the details here. If you prefer, create a stored procedure with a FOR-loop or do it in an 
-- external application (e.g. C# Console app). Performance is not important, since we are 
-- doing it only once. 

;WITH e1(n) AS 
(
    SELECT 1 FROM (VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(0)) t(n) 
) 
INSERT INTO dbo.TabOfEvents (Id) 
SELECT ROW_NUMBER() OVER (ORDER BY n10.n) AS n 
FROM 
e1 n10 
CROSS JOIN e1 n100 
CROSS JOIN e1 n1000 
CROSS JOIN e1 n10000 
CROSS JOIN e1 n100000 

でやり直すテーブルとシーケンスが設定されている、あなたは

UPDATE TabOfEvents 
SET cta = 'test', code = 'xxx', [date] = SYSDATETIME() 
FROM 
    TabOfEvents 
    INNER JOIN 
    (SELECT 
     NEXT VALUE FOR BufferPtr AS Ptr 
     FROM (VALUES (1)) t(n) 
    ) a 
    ON TabOfEvents.Id = a.Ptr; 
でレコードを更新することができます

ここでは、4つのレコードのみを使用してテストを確認できます(http://sqlfiddle.com/#!6/2679e/5/2)。 をクリックしてください。SQLを繰り返し実行すると、1つのサイクルでイベントがどのように追加されるのかがわかります。

注:私は最初にUPDATE TabOfEvents SET cta = 'test', code = 'xxx', [date] = SYSDATETIME() WHERE Id = NEXT VALUE FOR BufferPtrを使用しましたが、SQL ServerはWHERE句でシーケンスのクエリを拒否しました。私のUPDATE文を簡略化することはできますか?

+0

確かにバッファは私が必要なものです、それは自分自身を削除自分自身を完全に管理することができますが、私はそれを実装することができます理解できませんでした、または私のアプリケーションで? – lawir

+0

バッファのサイズは常に同じです。したがって、削除はもはや必要ではありません。データベースをセットアップするにはCREATE SEQUENCEが必要です(SQL Serverの構文を前提としていました)。 'UPDATE'はイベントをテーブルに入力するために必要なクエリです。エントリを循環的に置き換えます。 –

+0

私はテーブルにイベントを入力するためにクエリに挿入を使用して、私は必要なものではない行を正確に更新したいときに、更新クエリが必要です。作成シーケンスに関しては、おそらくそれはデータベースとプログラミングのC#で非常に新しいですが、私はそれを行うことができるクエリを知らないし、私は本当にこのシーケンスを作成する場所と方法を知らないもっと具体的にお願いしますか? – lawir

0

トリガーでこれを行うことができます。しかし、おそらくそれは必要ではありません。

テーブルの行を削除しても、自動的に領域が再利用されるわけではありません。データベーステーブルは、ファイルと同じように動作しません。行の削除は、ロギング、ロック、および索引の再編成のために(比較的)時間のかかる操作になる場合もあります。

パフォーマンスの観点から、うまく設計されたデータベースでは、多くの一般的な種類のクエリに対して、何百万行ものデータ行を処理する必要がありません。

テーブルのサイズを制限する場合は、パーティション方式を使用することをお勧めします。次に、スケジュールされたジョブを使用して古いパーティションを削除します。パーティションを削除するほうが個々の行を削除する方がはるかに効率的です。そして、削除されたパーティションからスペースを回復するのは簡単です。

+0

私はデータを永遠に保存できないため、データベースを制限する必要がありますか?パーティショニングスキームはどういう意味ですか?私は複数のテーブルを宣言したいのですか? – lawir

+0

テーブルの行を削除してもスペースが解放されないと言っているときは、空き領域がない行を削除しても意味がありますか? – lawir

+0

もちろん、データを "永遠"に保存することができます(妥当な値の "永遠"の場合)。データベース操作はスペースを使用します。厳密にはスペースが限られている環境にいる場合、ログ・スペースやページの断片化など、他の考慮事項もあります。 –

2

このようにしないでください。代わりにこれを行うことができます:

  • データとイベントの保存ポリシーおよび/またはアーカイブポリシーを設定します。たとえば、x月または日より古いイベントをアーカイブまたは削除することができます。異なるテーブルまたは別のデータベースにアーカイブすることができます。または、

  • イベントの許容量について、アプリケーションのビジネスレイヤーにルールを設定できます。この方法で、イベントやデータを好きなように制御し、制限することができます。第二の選択肢のために、最大のイベントは、データベースや設定(app.configをで、またはweb.configファイル)ファイルに設定テーブルのようなものに格納することができます数えるので


何か。オンラインで検索するとhow to read and write in config fileが見つかります。

はその後、挿入を行う前に、あなたのアプリケーションでは、などのデータベースからのイベントのカウントを取得:

SELECT COUNT(*) FROM events; 

はその後web.configファイルからの値でこの結果を比較します。値> =最大値の場合はエラーメッセージとともに挿入を拒否し、そうでない場合は挿入を行います。

+0

私は2番目のアイデアが好きです、より多くの詳細をお願いしますか? – lawir

+0

@lawirを挿入ロジックに追加し、いくつのイベントが存在するのかを確認し、挿入を許可または禁止します。これはデータベーストリガーで実行できます。また、これらがユーザーごとの場合は、各ユーザーに見積もりと同じ考えを与えることができます。挿入を許可または禁止できます。 –

+0

私はそのように考えてみましたが、私は多くの理由のために止めました。最も重要なのですが、私のID(プリミティブキー)を制限するためにはどうすればいいですか? – lawir

関連する問題