【问题标题】:Performance Issues with DB Design and Heavy Data数据库设计和大量数据的性能问题
【发布时间】:2012-06-01 19:20:41
【问题描述】:

我今天就我的应用程序中的数据库设计和性能问题提出了以下问题。

DB Design and Data Retrieval from a heavy table

但是,没有得到太多的回复。我不知道,我可能没有正确解释这个问题。现在,我重新定义了我的问题,希望得到专家的一些建议。

我在从特定表中选择数据时遇到性能问题。应用的业务逻辑如下: 我有许多导入过程,这些过程会导致在其父列名称下创建数据透视列,同时将它们显示给用户。随着列的旋转,系统需要时间将行转换为列,这会导致性能下降。 与此功能相关的数据库表如下: 可以有 N 个客户端。 CLT_Clients 表存储客户信息。

一个客户可以有 N 个项目。 PRJ_Projects 表存储项目信息和到客户端的链接。

一个项目可以有 N 个列表。 PRJ_Listings 表存储列表信息和项目链接。

可以有 N 个与列表关联的源实体。 ST_Entities 表存储源实体信息和列表链接。

此源实体是包含 InvestorID、头寸值、源日期、活动和公式状态的实际导入。

The name of the import e.g. L1Entity1 is stored in ST_Entities table alongwith ID field i.e. EntityID
InvestorID, Position, Source Date, Active and Formula values get stored in ST_Positions table 

数据库图

数据需要如下查看:

通过这种设计,我能够处理 N 次导入,因为 Position、Source Date、IsActive、Formula 列会被透视。

我在此设计中面临的问题是,当系统必须为超过 10-12 个源实体选择数据时,系统执行速度非常慢,并且要求显示大约 150 个源实体。因为数据不是按行存储的,我需要按列显示,因此编写动态查询来旋转这些需要很长时间的列。

问题 1: 请对我当前的数据库设计提出评论/建议,如果它是正确的,或者需要根据新设计进行更改,请为 Position、Source Date、IsActive、Formula 各取 150 列;以这种新方式,数据已经以我需要检索的方式存储,即我不必旋转/取消旋转它。但缺点是:

a) 此表中的列将超过 600 列?

b) 源实体将有限制,即 150 个。

问题 2:如果我需要坚持目前的状态,可以做些什么来提高性能?

请参阅下面的索引和枢轴方法信息:

关于 Position 表中的索引,我也采用了带有聚集索引的 ProjectID 字段,因为数据是根据 ProjectID 或 EntityID 从 Position 表中选择的。

当EntityID 用于从Position 表中选择数据时,它总是在JOIN 中使用。并且每当使用 ProjectID 从该表中选择数据时,它总是在 WHERE 中使用。

这里要注意的是,我在 ProjectID 上有一个聚集索引,但我没有在 Pivoted 列或 EntityID 上获取任何索引。这里有什么改进的余地吗?

使用的旋转方法:

Example 1:

'Select * From
(
    Select DD.InvestorID,Cast(1 As Bit) As IsDSInvestor,DD.Position,
    Case DD.ProjectID
    When ' + CAST(@ProjectID AS VARCHAR) +' Then DE.SourceName 
    Else ''' + @PPDeliveryDate + '''+DE.SourceName
    End As SourceName
    From DE_PositionData DD
    Inner Join DE_DataEntities DE ON DE.EntityID=DD.EntityID
    Where DD.ProjectID IN (' + CAST(@ProjectID AS VARCHAR) +',' + CAST(@PreviousProjectID AS VARCHAR) +') AND InvestorID IS NOT NULL

) IDD
Pivot
(
    max(Position) for SourceName in ('+ @DataColumns+')
) as p1'

示例2:

'Select * From
    (
        Select DD.InvestorID As DSSOFID,Cast(1 As Bit) As IsActiveInvestor,
        Case ST.SourceTypeCode
            When ''RSH'' Then Cast(IsNull(DD.IsActive,0) As Int)
            Else Cast(IsNull(DD.IsActive,1) As Int) 
        End As IsActive,
        ''~''+DE.SourceName As ActiveSourceName
        From DE_DataEntities DE
        Left Join DE_PositionData DD ON DE.EntityID=DD.EntityID
        Left Join 
        (
            Select * From #DataSources
            Where ProjectID=' + CAST(@ProjectID AS VARCHAR) +'
        ) ST ON ST.ESourceID=DE.ESourceID
        Where DE.ProjectID=' + CAST(@ProjectID AS VARCHAR) +' AND ST.SourceTypeCode NOT IN (''PBC'',''EBL'',''REG'')
        AND InvestorID IS NOT NULL

    ) IDD
    Pivot
    (
        Max(IsActive) for ActiveSourceName in ('+ @DataColumns+')
    ) As p1'

【问题讨论】:

  • 我认为您当前的 OLTP 架构没有问题。它似乎最适合您的追求。我认为你的报告布局是有问题的。你用什么来显示你的数据? Excel、SSRS、Web 表单等。无论哪种方式,我认为报告中的 600 列数据对于任何人来说都太多了。如果您可以详细说明您的报告媒介,或许可以建议更好的报告结构。您可能还想研究仓储数据和使用 SSAS。
  • Gareth,感谢您的快速回复。数据只需要在 Winform 中的网格中显示,用户可以在其中进行更改。这个 600 的数字是最坏的情况;网格中一般会有大约 150-200 列。
  • 如果在 Winforms 上完成,最好的解决方案是不具有分层表单结构,因此用户可以选择一个客户端,通过单击一个项目来查看项目,他们可以然后编辑项目详细信息并查看所有相关列表。通过单击列表,他们可以编辑列表并查看所有位置?我想这是个人喜好,但我更愿意开发这种结构,并更喜欢它作为用户。您还可以按需检索数据,并随时减少从数据库检索的数据量。
  • 抱歉 GarethD,我无法关注你。你同意我提出的数据库设计还是你有不同的想法?如果不同,请详细说明?
  • 总而言之,我同意您的数据库设计,但我认为在具有 100 列的表单上显示数据是个坏主意。你有关系数据,所以你应该这样显示它。也就是说,您可能不需要在一个表单上显示每一位数据,从顶层开始,然后从那里扩展。因此,一个显示所有客户的表单,一个显示客户详细信息和所有项目的客户表单,然后另一个显示一个项目和所有列表等的表单。

标签: sql-server-2008 database-design query-optimization database-performance


【解决方案1】:

我会建议以下内容。

您应该以标准化格式存储数据。您应该能够设置索引以使数据的旋转更快。如果您发布用于透视的实际查询,我们可能会提供帮助。

您希望以这种方式存储数据的原因有很多:

  • 重复块数量的灵活性
  • 许多数据库对表的列数或总宽度都有限制。您不希望您的设计接近这些限制。
  • 您可能需要有关每个块的附加信息。我总是在我的表中包含 CreatedBy 和 CreatedAt 列,并且您希望每个块都包含此列。
  • 您在摘要方面拥有额外的灵活性。
  • 添加/删除中间值很麻烦。

也就是说,透视表有一个关键优势:它是用户想要看到的。如果您的数据每天只更新一次,那么您应该使用数据透视表创建一个报表。

如果您的数据在一天中以增量方式更新,那么您可以设置触发器(或存储过程代码)来更新基表和报告摘要。

但正如我之前所说,您应该问另一个问题是您用于旋转的特定方法。也许我们可以提高那里的性能。

【讨论】:

  • 我已经编辑了我的问题并添加了有关使用的索引和 Pivot 方法的信息。
  • Gordon,您能否提供您对所使用的 Pivot 方法和索引的看法?
  • EntityId 是 DE_PositionData 的主键吗?将其作为 DE_DataEntities 上的索引的主键可能会对查询有很大帮助。
  • ListingID 是 DE_DataEntities 中的聚集索引,EntityID 是主键和非聚集索引。关于DE_PositionData,ProjectID是聚集索引,DataID是主键,这个表中没有EntityID上的Index。请建议是否需要更改?
猜你喜欢
  • 2011-06-22
  • 1970-01-01
  • 2017-07-22
  • 2012-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多