2017-12-24 1 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; 

가 .. 100000을 다르게 테이블을 만들고 빈 항목을 허용하고, 그런 다음 100000 개 빈 기록 및 IDS 1 테이블을 채우기

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) 
) 

IDS

를 입력 할 수 있도록 :이 데이터베이스에서 시퀀스 객체를 생성 우리는 미리 레코드 수를 알아 내고 쿼리를 저장하기 위해이 작업을 수행합니다. 즉, 삽입 또는 업데이트를해야하는지 알기 위해 레코드 수를 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을 반복적으로 실행하면 이벤트가 주기적으로 어떻게 추가되는지 확인할 수 있습니다.

참고 : 첫 번째 시도는 UPDATE TabOfEvents SET cta = 'test', code = 'xxx', [date] = SYSDATETIME() WHERE Id = NEXT VALUE FOR BufferPtr이지만 SQL Server는 WHERE 절의 시퀀스를 쿼리하지 않습니다. 내 UPDATE 문을 단순화 할 수 있습니까?

+0

실제로 필요한 버퍼가 무엇인지, 내가 원하는 것을 완벽하게 삭제 자체를 관리 할 수 ​​있지만 어떻게 구현할 수 있는지 이해하지 못했습니다, 그것은 SQL 쿼리입니까? 또는 내 신청서에? – lawir

+0

버퍼의 크기는 항상 동일합니다. 따라서 삭제는 더 이상 필요하지 않습니다. CREATE SEQUENCE는 데이터베이스를 설정하는데 필요할 것입니다 (SQL-Server 구문을 사용했습니다). 'UPDATE'는 이벤트를 테이블에 입력해야하는 쿼리입니다. 항목을 순환 방식으로 대체합니다. –

+0

필자는 insert into query를 사용하여 테이블에 이벤트를 입력합니다. 업데이트 쿼리는 필자가 필요로하지 않는 행을 정확하게 업데이트하고자 할 때 필요합니다. create sequence에 관해서는 아마도 데이터베이스와 프로그래밍 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

두 번째 아이디어가 마음에 듭니다. 자세한 내용을 알려 주실 수 있습니까? – lawir

+0

@lawir 삽입 논리에서 이벤트가 얼마나 있는지 확인한 후 삽입을 허용하거나 금지하십시오. 데이터베이스 트리거에서이 작업을 수행 할 수 있습니다. 또한 이들이 사용자별로 있다면 각 사용자에게 견적과 아이디어를 줄 수 있습니다. 삽입을 허용하거나 금지 할 수 있습니다. –

+0

나는 그 때 나는 많은 이유들 때문에 멈추었다고 생각했다. 가장 중요한 나의 ID (primery key)에 그것을 제한하기 위해 ifatat을 어떻게 할 것인가? – lawir

관련 문제