DB设计和重型数据的性能问题

时间:2012-06-01 19:20:42

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

我今天在我的应用程序中询问了有关数据库设计和性能问题的以下问题。

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 

数据库图表 DB Design

需要查看数据如下: Data View

通过这种设计,我可以处理N个导入,因为Position,Source Date,IsActive,Formula列得到了透视。

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

问题1:请对我当前的数据库设计进行评论/建议,如果它是正确的,或者需要使用新设计进行更改,请为150,每个位置,源日期,IsActive,Formula;以这种新方式,数据将以我需要检索的方式存储,即我不必转动/取消它。但缺点是:

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

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

问题2:如果我需要坚持现状,可以采取哪些措施来提高绩效?

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

关于位置表中的索引,我还使用聚簇索引获取了ProjectID字段,因为根据ProjectID或EntityID从位置表中选择了数据。

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

这里需要注意的是我在ProjectID上有一个Clustered索引,但我没有在Pivoted列OR 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'

1 个答案:

答案 0 :(得分:2)

我建议如下。

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

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

  • 重复块数的灵活性
  • 许多数据库对表的列数或总宽度有限制。您不希望您的设计接近这些限制。
  • 您可能需要有关每个块的其他信息。我总是在表格中包含CreatedBy和CreatedAt列,你会想要每个块。
  • 您在摘要方面具有额外的灵活性。
  • 添加/删除中间值非常麻烦。

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

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

但正如我之前所说,你应该问另一个问题是你用于旋转的特定方法。也许我们可以改善那里的表现。