Database design 存储和查询树的最有效方法是什么?

Database design 存储和查询树的最有效方法是什么?,database-design,Database Design,我需要分析1 TB+的web访问日志,特别是我需要分析与请求的URL和URL子集(子分支)相关的统计数据。如果可能的话,我希望查询能够在数据的小子集上快速进行(例如,1000万个请求) 例如,给定一个访问日志,其中请求了以下URL: /ocp/about_us.html /ocp/security/ed-209/patches/urgent.html /ocp/security/rc/ /ocp/food/ /weyland-yutani/products/ 我想进行如下查询: 计算所有“低

我需要分析1 TB+的web访问日志,特别是我需要分析与请求的URL和URL子集(子分支)相关的统计数据。如果可能的话,我希望查询能够在数据的小子集上快速进行(例如,1000万个请求)

例如,给定一个访问日志,其中请求了以下URL:

/ocp/about_us.html
/ocp/security/ed-209/patches/urgent.html
/ocp/security/rc/
/ocp/food/
/weyland-yutani/products/
我想进行如下查询:

  • 计算所有“低于”的请求数/ocp
  • 同上,但仅统计/ocp/security下的子节点请求
  • 返回请求频率最高的前5个URL
  • 同上,除按任意深度分组外
e、 g.对于上面的最后一个查询,数据的深度2将返回:

2: /ocp/security/
1: /ocp/
1: /ocp/food/
1: /weyland-yutani/products/
我认为理想的方法可能是使用列DB并标记URL,这样URL中的每个元素都有一列。然而,如果可能的话,我真的很想找到一种用开源应用程序实现这一点的方法。HBase是一种可能性,但查询性能似乎太慢,无法用于实时查询(另外,我也不想从事重新实现SQL的业务)


我知道有商业应用程序可以进行这种类型的分析,但出于各种原因,我希望自己实现它。

您可能希望在SQL Server 2008中签出HIERARCHYID数据类型,或在Oracle中签出其等效数据类型。

在投入太多时间在关系数据库之上设计分层数据结构之前,考虑在Bill Karwin演示的优秀反SQL反模式中阅读。比尔概述了以下开发层次结构的方法:

  • 路径枚举(幻灯片55)
  • 嵌套集(幻灯片58)
  • 闭合台(幻灯片68)

  • 树在数据库中通常不是很有效。我的意思是:如果你把树设计成真正的递归树,让项目指向它们的父节点,你会得到很多查询来查找所有的子节点

    但是您可以根据需要优化树

    将url的任何部分放入列中都不是一个坏主意。您需要将深度限制为一定数量的子节点。任何列上都可以有索引,这使得它非常快

    对这种结构的查询非常简单:

    Select count(*) From Hits where node1 = 'ocp' AND node2 = 'security';
    
    进行访问统计:

    SELECT node1, node2, count(*) as "number of hits"
    FROM hits 
    GROUP BY node1, node2
    ORDER BY count(*) DESC
    
    你会得到

    node1            node2        number of hits
    'ocp'                        23345
    'ocp'            'security'   1020
    'ocp'            'food'        234
    'weyland-yutani' 'products'     22
    
    您还可以按原样存储url,并使用正则表达式进行筛选。这更灵活,但速度较慢,因为您没有索引。您只需要限制url的整个长度,而不需要限制子节点的数量

    我认为你可以用任何足够好的数据库来存储大量数据。例如MySql。

    斯蒂芬·法鲁特的书中有一个非常优秀的章节(第7章-处理分层数据),其中解释并比较了使用关系数据库存储和查询树的3种方法


    如果您正在执行一个严肃的、具有行业实力的实施,那么学习本章将是一个很好的时间。

    我认为存储此类数据的最有效方法是在零件分解(或层次结构)表中

    零件分解表由三列组成:标识、父级和描述。对于示例数据,该表如下所示:

    Identity Parent Description
    0        Null   ocp
    1        0      about_us.html
    2        0      security
    3        2      ed-209
    4        3      patches
    5        4      urgent.html
    6        2      rc
    7        0      food
    8        Null   weyland-yutani
    9        8      products
    
    在填充URL(爆炸)表时,填充一个记录每个URL叶的表。根据示例数据:

     Leaf ID
    -------
    1
    5
    6
    7
    9
    

    我相信您可以从这两个表开始回答所有问题。

    要将树存储到数据库中,您可能需要研究嵌套集模型。因此,基本上,如果您不介意有一个额外的表-
    Closure table
    是迄今为止最好的解决方案。这似乎是一本很棒的书,但从我看到的情况来看,完全忽略了
    闭包表
    模式。