树形结构数据库 查询效率优化问题

vssvss 2010-02-08 05:54:28
现在我有一数据库 大约16万条 单表
结构式森林

B-D....
|
A-C-E....
|
F_G...
数据库中:
A,CEO,...
B,A,...
D,B,...
C,A,...
E,C,...
F,A,...
G,F,.....

....

现在又这样的需求,就是要找到某个节点下面的所有的孩子. 由于数据库是树形的
所以我写了几个函数:
findUser()就是查看数据库是否有这个人。
findManager()这个函数是找到父节点:如findManger(F)就是G
findUnder()这个就是找到第一层的子节点:如findUnder(A)就是B,C,F
遍历所以子节点的核心代码:
showlevel就是像下找几层:如AllUser(A,1)就是B,C,F;AllUser(A,2)就是B,C,F,D, E, G;
用的深度递归遍历。但是由于数据库很大,加上查询比较平凡。所以效率很低
一个有1万多点的节点要将近1个小时。
现在求一个比较好的解决方案,主要是尽量减少查询的时间。望高手解疑。有重分送上。

private ArrayList AllUser(string alias, int showlevel)
{
string row = findUser(alias);
ArrayList bm = new ArrayList();
if (string.Empty != row && showlevel > 0)
{
ArrayList sl = findUnder(alias);
for (int k = 0; k < sl.Count;k++ )
{
bm.Add((sl[k]).ToString());
}

int num = bm.Count;
for (int i = 0; i < num; i++)
{
string a = (string)bm[i];
if (showlevel > 1)
{
ArrayList bic = AllUser(a, showlevel - 1);
for (int k = 0; k < bic.Count; k++)
{
bm.Add(bic[k]);
}
}
}
}

return bm;
}
...全文
1269 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
vssvss 2010-02-09
  • 打赏
  • 举报
回复
引用 8 楼 cherishny 的回复:
建议用SQL 处理吧

说白了 SQL很麻烦,用ACCESS很方便, 有office的都有access
主要不是什么大的项目 是PM给我单独的活 目前开发测试都我一个人 用SQL不合适
vssvss 2010-02-09
  • 打赏
  • 举报
回复
有人给我说,Oracle比MySQL的功能要强大,其中有个重要的表现是可以简单地提取出整个树的所有节点。但我最近发现了一个替代的方法,大概Oracle也是差不多是这样弄得吧。

以前要提取树的节点,必须要用递归算法,多次连接数据库,导致效率问题。如今,通过一些字段设置,可以把问题简化。即把树形结构转换成单一列表。

要实现这一目的,我们的数据结构需要增加一个路径字段。每个节点都可以有一个从根节点开始到本节点的路径。如宇宙->银河系->太阳系->地球->中国。这个路径需要维护,每个节点改变了归属关系,都要把此节点相关的记录找出来重算。而且需要一定的储存空间,但这一字段可以存在另一个表里,不影响原表。

维护好路径后,就可以快速查找了。方法为:
1、以路径字段为排序字段来提取以某个节点为根的整个树。提取的节点当然也是以路径来比较。你会发现记录全部会与递归算法算出的排列顺序一样。所不同的是递归算法算出来的有层次,而现在的没有层次。但层次信息是有的,那就是路径。
2、以后的处理方式就仁者见仁、智者见智了。可以把这些记录做成数组,也可以在显示的时候慢慢判断这是在方案1 我觉得很不错 期待不同的解决方案
Cherishny 2010-02-09
  • 打赏
  • 举报
回复
建议用SQL 处理吧
vssvss 2010-02-09
  • 打赏
  • 举报
回复
我目前用的是ACCESS 2007, 我的元数据是存在txt里面的,选择access就是简单点 容易操作 很直观
vssvss 2010-02-09
  • 打赏
  • 举报
回复
引用 5 楼 sp1234 的回复:
呵呵,如果我操作客户端,我只能忍受10秒钟。

你有什么好的建议没 修改数据库结构也可以接受
  • 打赏
  • 举报
回复
呵呵,如果我操作客户端,我只能忍受10秒钟。
vssvss 2010-02-09
  • 打赏
  • 举报
回复
修改下:findManager()这个函数是找到父节点:如findManger(G)就是F
vssvss 2010-02-09
  • 打赏
  • 举报
回复
没有高手了 继续等待好的思路出现
ws_hgo 2010-02-08
  • 打赏
  • 举报
回复

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/ws_hgo/archive/2010/01/31/5274571.aspx

create table #EnterPrise
(
Department nvarchar(50),--部门名称
ParentDept nvarchar(50),--上级部门
DepartManage nvarchar(30)--部门经理
)
insert into #EnterPrise select '技术部','总经办','Tom'
insert into #EnterPrise select '商务部','总经办','Jeffry'
insert into #EnterPrise select '商务一部','商务部','ViVi'
insert into #EnterPrise select '商务二部','商务部','Peter'
insert into #EnterPrise select '程序组','技术部','GiGi'
insert into #EnterPrise select '设计组','技术部','yoyo'
insert into #EnterPrise select '专项组','程序组','Yue'
insert into #EnterPrise select '总经办','','Boss'
--查询部门经理是Tom的下面的部门名称
;with hgo as
(
select *,0 as rank from #EnterPrise where DepartManage='Tom'
union all
select h.*,h1.rank+1 from #EnterPrise h join hgo h1 on h.ParentDept=h1.Department
)
select * from hgo
/*
Department ParentDept DepartManage rank
--------------- -------------------- ----------------------- -----------
技术部 总经办 Tom 0
程序组 技术部 GiGi 1
设计组 技术部 yoyo 1
专项组 程序组 Yue 2
*/
--查询部门经理是GiGi的上级部门名称
;with hgo as
(
select *,0 as rank from #EnterPrise where DepartManage='GiGi'
union all
select h.*,h1.rank+1 from #EnterPrise h join hgo h1 on h.Department=h1.ParentDept
)
select * from hgo
/*
Department ParentDept DepartManage rank
-------------------- ---------------------- ----------- -----------
程序组 技术部 GiGi 0
技术部 总经办 Tom 1
总经办 Boss 2
*/
flyerwing 2010-02-08
  • 打赏
  • 举报
回复
减少查询时间,要么减少循环次数,要么提高循环的效率。
递归应该是不错的选择吧

110,549

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧