用depth字段优化指定深度节点的查询
2013-12-03 00:00
357 查看
回到我们之前的数据库字段设计,我们知道 parentid 可以和 id 字段结合来输出无限级分类的输出,还能用来表示节点间的关系。
这种设计用得很普遍,而且是最省存储空间,但是却不是最有效率的。比如现在我们有这么一个需求,需要查询指定深度节点时就会遇到问题。因为是采用递归(递归的效率你懂的)的方法,我们需要通过递归来逐层展开才能获取到所有该层的节点,然后再在其中进行查询实在既浪费时间又浪费空间。那么有没有更好的做法呢?
现在再来看看我的设计,增加了两个字段:depth 和 parentid_list。
depth 表示当前节点的深度的整数。
parentid_list 表示从根节点到当前节点的路径的字符串,采用节点名称不可能出现的字符作为分隔符。
现在输出树状结构:
观察层级关系字段 parentid_list,和深度字段 depth,维护它们其实并不会很费力,因为有迹可寻的,用程序自动维护也是可以的。但是在查询的时候这两个字段却能给我们带来很大的便利,比如我们需要查询所有第三层的节点:
再比如我们要查询“家用电器”节点的“大家电”节点下的所有子节点,则可以这么写:
换作用递归来实现,就可能没那么高效,而且也没有这么直观。这样做的道理就在于,通过增加冗余信息来提高检索速度,同时这些冗余信息非常容易维护所以不容易因为操作不慎而导致信息不一致。
当然我的设计并不完善,上面仅仅只谈了益处,如果你觉得这个设计不好,也可以只使用普遍使用的递归方式。
这种设计用得很普遍,而且是最省存储空间,但是却不是最有效率的。比如现在我们有这么一个需求,需要查询指定深度节点时就会遇到问题。因为是采用递归(递归的效率你懂的)的方法,我们需要通过递归来逐层展开才能获取到所有该层的节点,然后再在其中进行查询实在既浪费时间又浪费空间。那么有没有更好的做法呢?
现在再来看看我的设计,增加了两个字段:depth 和 parentid_list。
depth 表示当前节点的深度的整数。
parentid_list 表示从根节点到当前节点的路径的字符串,采用节点名称不可能出现的字符作为分隔符。
现在输出树状结构:
观察层级关系字段 parentid_list,和深度字段 depth,维护它们其实并不会很费力,因为有迹可寻的,用程序自动维护也是可以的。但是在查询的时候这两个字段却能给我们带来很大的便利,比如我们需要查询所有第三层的节点:
mysql> SELECT * FROM categories WHERE depth = '3'; +----+---------------+---------+----------+---------------+-------+-------+----------+ | id | name | xname | parentid | parentid_list | depth | state | priority | +----+---------------+---------+----------+---------------+-------+-------+----------+ | 3 | 计算机/互联网 | NULL | 2 | 1,2,3 | 3 | 1 | 0 | | 4 | 医学 | NULL | 2 | 1,2,4 | 3 | 1 | 0 | | 5 | 自然与科学 | NULL | 2 | 1,2,5 | 3 | 1 | 0 | | 8 | 笔记本 | NULL | 7 | 6,7,8 | 3 | 1 | 0 | | 9 | 平板电脑 | NULL | 7 | 6,7,9 | 3 | 1 | 0 | | 10 | 服务器 | NULL | 7 | 6,7,10 | 3 | 1 | 0 | | 13 | 电饭锅 | cookers | 12 | 11,12,13 | 3 | 1 | 0 | | 15 | 冰箱 | NULL | 14 | 11,14,15 | 3 | 1 | 0 | | 16 | 洗衣机 | Washer | 14 | 11,14,16 | 3 | 1 | 0 | +----+---------------+---------+----------+---------------+-------+-------+----------+ 9 rows in set
再比如我们要查询“家用电器”节点的“大家电”节点下的所有子节点,则可以这么写:
mysql> SELECT * FROM categories WHERE parentid_list LIKE '%11,14,%'; +----+--------+--------+----------+---------------+-------+-------+----------+ | id | name | xname | parentid | parentid_list | depth | state | priority | +----+--------+--------+----------+---------------+-------+-------+----------+ | 15 | 冰箱 | NULL | 14 | 11,14,15 | 3 | 1 | 0 | | 16 | 洗衣机 | Washer | 14 | 11,14,16 | 3 | 1 | 0 | +----+--------+--------+----------+---------------+-------+-------+----------+ 2 rows in set
换作用递归来实现,就可能没那么高效,而且也没有这么直观。这样做的道理就在于,通过增加冗余信息来提高检索速度,同时这些冗余信息非常容易维护所以不容易因为操作不慎而导致信息不一致。
当然我的设计并不完善,上面仅仅只谈了益处,如果你觉得这个设计不好,也可以只使用普遍使用的递归方式。
相关文章推荐
- Runtime.getRuntime.exec(String)与exec(String[])的区别
- tar time stamp in the future问题
- 浅析【缤纷桌面】
- 程序员的开源精神真的不错
- 简易javascript遮罩层提示框
- JUnit4 学习总结
- 就开会
- mark
- a
- Mysql左连接,右连接,内连接的区别
- Mysql修改root密码
- java mysql latin1繁体中文乱码问题
- WebView 总结
- How to Enable PS Remote
- spark的几点备忘
- Flex 子界面调用父界面的方法
- ZOJ 3736 Pocket Cube
- xdebug php
- Android SlidingMenu 的实现
- 关于《C语言深度解剖》一些例程的实验和感悟——关键字static