2008-12-10 87 views
4

我正在进行分层数据库结构的设计,该分层数据库结构对包含产品的目录建模(这与this question类似)。数据库平台是SQL Server 2005,目录非常大(750,000个产品,超过4个级别的8,500个目录部分),但相对静态(每天重新加载一次),所以我们只关注READ性能。分层数据结构设计(嵌套集)

目录分层结构的一般结构是: -

  • 1级第
    • 2级第
      • 3级第
        • 等级4组(产品有链接到这里)

我们使用嵌套存储的层级和存储其存在在一个单独的链接表该级别的产品设置模式。因此,简化数据库结构将是

CREATE TABLE CatalogueSection 
(
    SectionID INTEGER, 
    ParentID INTEGER, 
    LeftExtent INTEGER, 
    RightExtent INTEGER 
) 

CREATE TABLE CatalogueProduct 
(
    ProductID INTEGER, 
    SectionID INTEGER 
) 

我们确实有在一个更加复杂,我们有大约1000不同的客户群体可能会或可能不会看到所有目录中的产品。因此,我们需要为每个客户群维护一个单独的“副本”,以便当他们浏览目录时,他们只能看到他们的产品,而且他们也看不到任何空的部分。

为了便于实现,我们在下面的部分中维护了一个层次结构的每个级别的产品数量表。因此,即使产品仅与层次结构的最低级别直接相关,它们也会一直统计在树上。此表的结构是

CREATE TABLE CatalogueSectionCount 
(
    SectionID INTEGER, 
    CustomerGroupID INTEGER, 
    SubSectionCount INTEGER, 
    ProductCount INTEGER 
) 

所以,在这个问题 表现在层次结构的顶部水平很差。在所选目录部分(以及所有子部分)中显示“前10名”产品的一般查询需要在1分钟左右的时间内完成。在层次结构的较低部分,速度较快,但仍不够好。

我已经在所有关键表上放置了索引(包括覆盖索引),通过查询分析器,索引调整向导等来运行它,但仍然无法使其执行得足够快。

我想知道设计是否存在根本上的缺陷,或者是否因为我们有这么大的数据集?我们有一个合理的开发服务器(3.8GHZ Xeon处理器,4GB内存),但它只是不工作:)

感谢所有帮助

詹姆斯

+1

也许这会有助于向我们展示缓慢的SQL?我们可能会发现一些会造成瓶颈的东西。 – Jonathan 2008-12-10 10:53:09

回答

6

使用封闭台。如果基本结构是具有字段ID和ParentID的父子,则封闭表的结构是ID和DescendantID。换句话说,封闭表是祖先后裔表,其中每个可能的祖先都与所有后代相关联。如果需要,您可以包含一个LevelsBetween字段。闭包表实现通常包括自引用记录,即,ID 1是LevelsBetween为零的后代ID 1的祖先。

示例: 父/子
PARENTID - ID
1 - 2
1 - 3
3 - 4
3 - 5
4 - 6

祖先/后代
ID - DescendantID - LevelsBetween
1 - 1 - 0
1 - 2 - 1
1 - 3 - 1
1 - 4 - 2
1 - 6 - 3
2 - 2 - 0
3 - 3 - 0
3 - 4 - 1
3 - 5 - 1
3 - 6 - 2
4 - 4 - 0
4 - 6 - 1
5 - 5 - 0

表旨在消除递归连接。将递归连接的负载加载到您每天加载数据一次的ETL循环中。这将它从查询中移开。

此外,它允许可变级别的层次结构。您将不会被卡在4.

最后,它允许您在非叶节点中插入产品。很多目录在层次结构的更高层创建“杂项”存储桶以创建附加产品的叶节点。由于中间节点包含在闭包中,因此不需要这样做。

就索引来说,我会在ID/DescendantID上做一个聚集索引。

现在为您的查询性能。这需要大块,但不是全部。你提到了一个“前十名”。这意味着对你没有提及的一系列事实进行排序。我们需要细节来帮助调整这些。另外,这只会得到叶级别的部分,而不是产品。至少,您应该在您的CatalogueProduct上有一个按SectionID/ProductID命令的索引。我会强制Section到Product连接是基于您提供的基数的循环连接。关于目录部分的报告将转到封闭表以获取后代(使用聚集索引查找)。后代列表将被用于通过循环索引查找使用索引从CatalogueProduct获取产品。然后,通过这些产品,您将获得进行排名所需的事实。

0

您可能能够解决客户群体问题的角色和treeId的,但你必须向我们提供查询。

0

可能在每天加载后计算ProductCount和SubSectionCount?
如果数据一天只改变一次,那么即使需要一些非规范化,计算这些数字也是值得的。

+0

是的,我们已经预先计算每天。这不是计算产品的问题,而是显示选定部分中实际产品列表缓慢。 – James 2008-12-10 15:23:26

+0

您是否在重新加载数据后更新统计信息? 如果你的索引是好的(调整为只读使用),那么它可能是你回来太多的数据?这是我可能接下来要看的一个领域。 TBH,在没有看到架构和/或存储过程的情况下帮助更多人将会相当困难。 – Bravax 2008-12-10 15:32:39