简体   繁体   English

使用实体框架时规范化SQL表

[英]Normalizing SQL table while using Entity Framework

Let me start by saying I am not a SQL expert, novice is appropriate 首先,我不是SQL专家,适合新手

I have a log table which currently has 10 million rows: 我有一个日志表,当前有1000万行:

Logs( Id, FKId, Source, Message )

I am wondering if it would be beneficial to Normalize my table for Source and Message. 我想知道规范化我的源和消息表是否有益。 Of the 10m rows there are only 200,000 DISTINCT Source's and 1 million Distinct Messages. 在1000万行中,只有200,000个DISTINCT源的消息和100万个Distinct消息。 To normalize this data I assume I would need two more tables. 为了规范化此数据,我假设我将需要两个以上的表。 a Source with Id and Text, and a Message with Id and Text (or perhaps they could be the same table?) 具有ID和文本的源,以及具有ID和文本的消息(或者它们可能是同一张表?)

I am using Entity Framework currently to insert rows. 我目前正在使用实体框架插入行。 I am wondering how Entity Framework would handle this and if I would get the performance boost I am looking for, specifically when trying to do "Message LIKE '%error%'", or just in general by making the whole thing smaller thus less paging. 我想知道Entity Framework如何处理这个问题,是否可以提高我想要的性能,特别是在尝试执行“ Message LIKE'%error%'”时,或者通常是通过使整个事情变小从而减少分页来实现? 。

I assume there is no way that EF will automatically figure out for me if the Message of the new insert is unique so I would have to figure that out before hand or do the insert via a Stored Procedure instead. 我认为如果新插入的消息是唯一的,EF将无法自动为我确定,因此我必须事先弄清楚这一点,或者通过存储过程来进行插入。 If i'm doing 2 million inserts a day to this table how does calling a SP via EF change in terms of performance vs 如果我每天要执行200万次插入该表,那么通过EF调用SP的性能与

context.Logs.Add(log)
context.Save();

I assume your C# code would have a method signature like this: 我假设您的C#代码将具有以下方法签名:

public void AddLogMessage(Int32 foreignKeyId, String source, String message)

If you modify your DB design to be like this: 如果将数据库设计修改如下:

Logs( LogId, FKId, SourceId, MessageId )
Sources( SourceId, Value )
Messages( MessageId, Value )
-- with all appropriate FK constraints on Logs->Sources and Logs->Messages

...then you'll find yourself writing more C#/Linq than is necessary to lookup the source and message text and put them into the record (in addition to using more DB chatter). ...然后,您会发现自己编写的C#/ Linq比查找源和消息文本并将其放入记录所需的更多(除了使用更多的DB聊天记录之外)。 Pragmatically this is best done with a Stored Procedure that you would add to your DBContext as a Function Import: 实用上最好用存储过程来完成,您可以将它作为函数导入添加到DBContext中:

CREATE PROCEDURE AddLogMessage
    @fkId int,
    @source nvarchar(255),
    @message nvarchar(1024)
AS
BEGIN
    SET NOCOUNT ON

    BEGIN TRANSACTION

    DECLARE @sourceId int = SELECT SourceId FROM Sources WHERE Value = @source
    IF @sourceId IS NULL
    BEGIN
        INSERT INTO Sources ( Value ) VALUES ( @source )
        SET @sourceId = SELECT SCOPE_IDENTITY()
    END

    DECLARE @messageId int = SELECT MessageId FROM Messages WHERE Value = @message
    IF @messageId IS NULL
    BEGIN
        INSERT INTO Messages ( Value ) VALUES ( @message)
        SET @messageId = SELECT SCOPE_IDENTITY()
    END

    INSERT INTO Logs ( @fkId, @sourceId, @messageId )

    COMMIT TRANSACTION

END

After you've imported it into your DBContext, just call it like any other function: 将其导入到DBContext中之后,就可以像调用其他函数一样调用它:

public void AddLogMessage(Int32 foreignKeyId, String source, String message) {
    this.dbContext.AddLogMessage( foreignkeyId, source, message );
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM