性能的考虑:传播行在多个表vs集中所有行在一个表中。

我需要登录的信息,关于每一步骤,继续在应用程序在SQL数据库。有一些表格,我想让日志应当是相关的:产品应该记录的,当一个产品已经建立的改变等等。令-同上 航运相同的 等等。等等。等等。

数据将需要检索经常。

我有些想法就如何做到这一点:

  1. 有一个记录表将包含列对所有这些表格,然后当我想表示数据的用户界面为一些产品将做select*from日志LogId=产品。ProductId.我知道这可能是很有趣,有很多cols,但我有这种感觉,能会更好。在另一方面会有大量的排在本表格。
  2. 有许多记录表为每个日志的类型(ProductLogs,OrderLogs等)。 我真的不喜欢这个想法,因为它是不一致的,有许多表格结构相同的结构是没有意义的,但是(?) 它可能是更快,当搜索一个表格,具有低量的行(m我错了吗?).
  3. 根据发言。1,我可以做一件第二多的一个表,将有LogId,TableNameId和RowId cols,并将参考一个记录行的许多表行在数据库,不会有一个名检索的数据(例如日志id234表属于客户的层345和产品表productId=RowId);我认为这是最好的方式做到这一点,但是,可能有大量的排,将它慢下来搜索?或者这是如何它应该做的,你会怎样说?...

例没有。3在上述清单:

CREATE TABLE [dbo].[Log](
    [LogId] [int] IDENTITY(1,1) NOT NULL,
    [UserId] [int] NULL,
    [Description] [varchar](1024) NOT NULL,
 CONSTRAINT [PK_Log] PRIMARY KEY CLUSTERED 
(
    [LogId] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO
ALTER TABLE [dbo].[Log]  WITH CHECK ADD  CONSTRAINT [FK_Log_Table] FOREIGN KEY([UserId])
REFERENCES [dbo].[Table] ([TableId])
GO
ALTER TABLE [dbo].[Log] CHECK CONSTRAINT [FK_Log_Table]
---------------------------------------------------------------------
CREATE TABLE [dbo].[LogReference](
    [LogId] [int] NOT NULL,
    [TableName] [varchar](32) NOT NULL,
    [RowId] [int] NOT NULL,
 CONSTRAINT [PK_LogReference] PRIMARY KEY CLUSTERED 
(
    [LogId] ASC,
    [TableName] ASC,
    [RowId] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO
SET ANSI_PADDING OFF
GO
ALTER TABLE [dbo].[LogReference]  WITH CHECK ADD  CONSTRAINT [FK_LogReference_Log] FOREIGN KEY([LogId])
REFERENCES [dbo].[Log] ([LogId])
GO
ALTER TABLE [dbo].[LogReference] CHECK CONSTRAINT [FK_LogReference_Log]
---------------------------------------------------------------------
CREATE FUNCTION GetLog
(   
    @TableName varchar(32),
    @RowId int
)
RETURNS 
@Log TABLE
(       
    LogId int not null,
    UserId int not null,
    Description varchar(1024) not null
)
AS
BEGIN

INSERT INTO @Log
SELECT     [Log].LogId, [Log].UserId, [Log].Description
FROM         [Log] INNER JOIN
                      LogReference ON [Log].LogId = LogReference.LogId
WHERE     (LogReference.TableName = @TableName) AND (LogReference.RowId = @RowId)
    RETURN 
END
GO
有帮助吗?

解决方案

我肯定会去的选择3,对于几个原因:

数据应该在该领域的一个表,而不是作为一个表名(选择方案2)或一个域名(备选1).这样的数据库获取的工作更容易和更容易维护。

窄表genrally更好地执行。行数少的性能产生影响的比数领域。

如果你有一个领域的每个表(备选方案1),则可能会得到很多空领域时,只有少数几个表格都受到一种操作。

其他提示

小心preoptimizing数据库。大多数数据库是合理的快速和有些复杂。你要运行一个试验对于效率的第一个。

第二把一切都放在一个表格,使它更有可能你想要的结果是在高速缓存这将加速性能极大。不幸的是,这也使得它更有可能你会得到搜寻一个巨大的表来找到你正在寻找。这可以部分解决的索引,但是索引也不是免费的(他们使文字更加昂贵,对于一个)。

我的建议是要做一个测试看看如果性能真正的问题,然后测试不同的方案来看这是最快的。

如果你说的是大量数据(数以百万计的行+),然后你会得到有益利用不同的表来存放他们。

例如基本的例子50万日志条目的,假设5个不同的"类型"的记录表 最好有5×10亿行表于1×50万的行表

  • 插入绩效将会更好地与各个表格-索引的每个桌会更小,因此更快的/更容易被更新/维持的一部分插入操作

  • 读性将可以更好地与各表的数据来查询,较小的索引遍历。此外,听起来像你会需要存储的额外列,以确定哪种类型的登录入一个记录是(产品,运输。...)

  • 维持在较小的表小痛苦(统计、指数整理/重建等)

从本质上讲,这是有关划分的数据。从SQL2005年起,它已经建立在支持分区(见 在这里,)但是你需要的企业版,其基本上可以让你分区的数据在一个表格,以提高性能(例如你会有你的一个日志表,然后如何定义内的数据是分配)

我听到一次采访中的一个eBay建筑师最近,他强调重要的分区时需要的性能和可伸缩性,我强烈同意根据我的经验。

试图实现数据访问层的方式这样你可以改变从一个数据库模型的另一个如果需要的-这样,你随便挑一个和担心其性能的影响后。

不做性能检测,并有一个准确的想法的各种载荷你会得到它的将是难以优化作为性能取决于一些因素,例如数量的读、写入数,以及是否读和写可能的冲突,并导致锁。

我倾向于备选案文1顺便说一句-其最简单的做和有许多调整,你可以做的来帮助解决各种各样的问题。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top