日志表

时间:2017-03-20 07:58:16

标签: sql indexing sql-server-2008-r2

我必须在我的应用程序中进行一些登录。每日有效载荷约为50000次插入。我必须存储几个字段,最重要的 - 事件类型和事件日期/时间。会有排序,分页和过滤的查询。我应该创建哪些索引(在哪些字段上以及群集或非群集)以缩小插入和查询时间(至少对于选择..在上面的字段中的位置)?谷歌搜索给出了关于子项目的各种想法,所以我无法弄清楚要做什么

UPD 我的POCO:

public class LogEntry
{
    public DateTime LoggedAt { get; set; }
    public int EventType { get; set; }
    public bool IsSuccesful { get; set; }
    public string Message { get; set; }
    public string URL { get; set; }
    public string Login { get; set; }
    public string IP { get; set; }
    public string UserAgent { get; set; }
}

最常见的查询是select .. where (LoggedAt between .. and ..) and (EventType=..)。有时,and条款可能会有其他where部分。 也没有计划更新操作。删除是可能的,但只是偶尔由lagre批量删除。

2 个答案:

答案 0 :(得分:1)

以下陈述仅适用于一些可能的情况。 Ofc很难为您提供特定的解决方案(您必须描述您的选择性)。但你可以在这里看到一些观点,也许它可以帮助你。

可以帮助你的一些标准:
更多索引 - >最难插入的 - 尽可能多的独特价值,为大多数选择性做最好的指数...

聚集索引 - 用B-Tree替换你的堆

非聚集索引 - 将页面引用到您的堆(创建新对象) - 消耗更多空间 - >索引+数据

-- your table should seems like :
CREATE TABLE LogEntry (LoggedAt     DATETIME,
                       EventType    INT,
                       IsSuccesful  BIT,
                       Message      VARCHAR(511),--check your input to set it correctly
                       URL          VARCHAR(511),--check your input to set it correctly
                       Login        VARCHAR(127),--check your input to set it correctly
                       IP           VARCHAR(63),--check your input to set it correctly
                       UserAgent    VARCHAR(63))--check your input to set it correctly

-- For examlle for following select
SELECT * 
FROM LogEntry 
WHERE LoggedAt BETWEEN GETDATE() AND DATEADD(dd,-1,GETDATE()) AND
      EventType = 1

-- can help following index (ofc unique values is best for clustered indexes)
CREATE CLUSTERED INDEX idx_LogEntry_LoggedAt_EventType ON dbo.LogEntry (LoggedAt,EventType)

-- For example for following select
SELECT Message 
FROM LogEntry 
WHERE LoggedAt BETWEEN GETDATE() AND DATEADD(dd,-1,GETDATE()) AND
      EventType = 1
-- can help following index 
CREATE NONCLUSTERED INDEX idx_LogEntry_LoggedAt_EventType ON dbo.LogEntry (LoggedAt,EventType) INCLUDE (Message)

-- and so ... it really depends what you really want...

-- for me can be really helpfull following solution:
CREATE TABLE LogEntryO (LogEntryId INT IDENTITY PRIMARY KEY CLUSTERED, -- my clustered index
                       LoggedAt     DATETIME,
                       EventType    INT,
                       IsSuccesful  BIT,
                       Message      VARCHAR(511),--check your input to set it correctly
                       URL          VARCHAR(511),--check your input to set it correctly
                       Login        VARCHAR(127),--check your input to set it correctly
                       IP           VARCHAR(63),--check your input to set it correctly
                       UserAgent    VARCHAR(63))--check your input to set it correctly
-- + following index
CREATE NONCLUSTERED INDEX idx_LogEntryO_LoggedAt_EventType ON dbo.LogEntryO (LoggedAt) INCLUDE (LogEntryId)

-- and my query should seems

;WITH CTE AS (SELECT LogEntryId FROM dbo.LogEntryO WHERE LoggedAt BETWEEN GETDATE() AND DATEADD(dd,-1,GETDATE()))
SELECT *
FROM dbo.LogEntryO a
JOIN CTE b ON a.LogEntryId = b.LogEntryId
WHERE a.EventType = 1

为您创建最佳解决方案真的很难,因为您似乎使用c#class来访问此表。例如,您可以使用某种ORM,例如实体框架或soo ......

答案 1 :(得分:0)

如果没有更多信息,很难给出具体答案。无论如何,我认为你可以尝试在你最重要的两个领域使用索引。 记住(但可能你已经知道),对于你所做的查询,字段的顺序很重要 如果您知道查询始终相同,则可以添加其他字段(在索引中或使用INCLUDE列)。 评估"基数"这些领域的价值也是如此。 如果可能,请经常查看MSSQL存储的有关索引使用情况的信息 如果是OLTP系统,频繁更新/删除,则添加过多索引可能不是正面的。