查询在数据库中搜索树

时间:2010-02-08 21:01:13

标签: sql ms-access nested-sets tree

我的数据库中有一个代表树的表。数据使用nested sets存储。我想编写一个查询来搜索树,并返回与模式匹配的节点,以及它们的祖先和后代。这就是我到目前为止所提出的。

SELECT DISTINCT Node, Parent, Description
FROM Hierarchy 
INNER JOIN 
    (SELECT Lft, Rgt 
    FROM Hierarchy 
    WHERE Description LIKE '%SEARCHQUERY%') AS Matches 
ON (Hierarchy.Lft <= Matches.Lft AND 
    Hierarchy.Rgt >= Matches.Rgt) OR 
    (Hierarchy.Lft >= Matches.Lft AND 
    Hierarchy.Rgt <= Matches.Rgt) 
ORDER BY Description

此查询有效,但当子查询与大量描述匹配时,它有点慢。我正在寻找有关如何提高此查询性能的想法。

如果相关,我正在使用Access。

我有空并且愿意更改表的结构以改进此查询。该表有大约8000个节点。在应用程序的生命周期内,记录数量不会发生太大变化。最大深度为五。

对于常规搜索,性能是可接受的(对于返回~200个节点的搜索,几秒钟),但在病态情况下,它需要几分钟(例如,如果搜索单个元音。但即使在这些情况下,子查询执行时间不到一秒钟。

3 个答案:

答案 0 :(得分:1)

我可能会偏离原来的问题,但我在这里:

正如评论中所建议的那样,考虑到你可以负担得起重写,你应该研究一种不同的方式来建模树形结构,特别是考虑到你有一个“固定深度”,用不同的方法可以很容易管理。

Faroult在他的“SQL的艺术”中赞成一种方法,该方法基于在编码节点所在的“分支”的字符串字段中表示节点的位置。 (有关该书的评论和一些讨论,请参阅 this Slashdot thread )。

这是我的意思的 online example - SQL的艺术有本书的一部分专门用于此,比较三种不同的方法(嵌套集,父/子关系)表,编码路径字段)并使用滑铁卢军队的战斗秩序作为例子(有大量的查询,如“列出X将军下的所有营”或“查找谁是炮兵团Y的指挥官”)。

Faroult对性能非常狂热,整本书是非供应商特定的集合,提供了关于如何(重新)编写高效查询的非常合理和实用的建议。

答案 1 :(得分:0)

我可能只在表中使用parent_id字段,并使用3向外部自联接来获取目标hierarchy记录(适当过滤)及其父级(如果有的话) )和孩子(如果有的话)记录。

答案 2 :(得分:0)

查询速度慢的原因是LIKE('%blah%')部分。如果你可以放弃第一个%事情会明显加快。或者,如果 Access支持FULLTEXT索引,则在“说明”字段中添加一个并执行MATCH(Description) AGAINST ('blah')