2017-09-19 90 views
1

我有一個日誌記錄表,它記錄應用程序中的事件,但在嘗試刪除舊條目時,服務器速度變慢並阻止應用程序使用數據庫。我希望能夠快速刪除超過30天的日誌條目,而不會中斷創建新日誌事件或禁止其他數據庫操作。刪除日誌表上的性能

信息:

  • 的記錄表中​​插入每天約300,000行所以一般它會 擁有約10萬行一個月的日誌記錄。

  • 我使用了一個相當薄弱的機器,4GB內存

  • 上有一個ID字段中的PK指數,但沒有其他指標或外國 鍵在SQL Express服務器。

  • 此表不用於日誌以外的任何操作,因此不會執行其他任何操作。

表模式:

CREATE TABLE [dbo].[LogEvents](
    [Id] [bigint] IDENTITY(1,1) NOT NULL, 
    [Occurred] [datetime] NOT NULL, 
    [Message] [nvarchar](max) NOT NULL, 
    [Severity] [nchar](10) NOT NULL, 
    [Source] [nvarchar](50) NOT NULL, 
    [LotNo] [nchar](10) NULL, 
    [Code] [int] NULL, 
PRIMARY KEY CLUSTERED ([Id] ASC) 

目前我的應用程序中調用以下存儲過程的每一分鐘來清除舊日誌中的批次。 (讓@days = 30)

CREATE PROCEDURE [dbo].[ClearLogsOlderThan] 
@Days int 
AS 
DELETE TOP (4500) from LogEvents 
WHERE DATEDIFF(dy, [Occurred], GETDATE()) > @Days 

我的問題:

  1. 有沒有更好的方式來刪除舊行?

  2. 執行計劃顯示正在使用PK索引,但會在datetime列上的索引更好,因爲這就是我實際上正在比較的內容?

  3. 不斷刪除舊行並插入新記錄會破壞索引的有效性嗎?它需要經常重建嗎?新行應始終是順序的,只有舊行纔會被刪除。

  4. 下面的查詢理論上會工作得更快嗎?比較執行計劃表明它會,但我希望得到第二個意見。聲明@oldID是一個INT而不是像PK列一樣的BIGINT會有性能下降嗎?

QUERY:

DECLARE @oldID as int; 
SET @oldID = (SELECT TOP 1 [Id] 
       FROM [LogEvents] 
       WHERE DATEDIFF(DY, [Occurred], GETDATE()) > 30 
       ORDER BY [Id] DESC) 
DELETE TOP (4500) FROM LogEvents 
WHERE [Id] <= @oldID 
+1

您是否需要每分鐘清潔一次日誌表?或者你可以在夜間服務器有更多的可用空間時做到這一點? – LONG

+0

@LONG這是記錄數據的機器是在一條可能運行24/7的生產線上。我不想引起任何形式的操作限制,僅僅因爲日誌需要被清除,除非它真的需要它。 – EMUEVIL

回答

3

清除此頻繁似乎有點矯枉過正,特別是因爲沒有訂單通過查詢你不指定4500行日誌。但最大的問題是你的查詢不可用,因爲你的列中有一個函數。在getdate上進行datemath,至少你的查詢可以利用Occurred列的索引。

我使用ABS()* -1,以便任何現有的代碼仍然可以正常工作。

where Occurred < dateadd(day, abs(@Days) * -1, getdate()) 
+0

謝謝!所以我應該在[Occurred]列上創建一個索引,並調整我的查詢以隔離函數外的發生列? 我沒有包括這個順序,因爲我不關心哪個舊行被首先刪除。可以執行一個命令來提高速度嗎? – EMUEVIL

+0

沒有,如果有的話會減慢速度。爲什麼這樣一個奇數,如果你不關心哪些被刪除? –

+0

我在某處讀取一次刪除5000或更多行將強制整個表鎖定。那麼......迷信? https://technet.microsoft.com/en-us/library/ms184286(v=sql.105).aspx 所以我應該添加一個索引到Occurred列? – EMUEVIL