• 用depth字段优化指定深度节点的查询

    depth与层级关系的设计
    服务器君一共花费 19.355 ms 进行了 2 次数据库查询,努力地为您提供了这个页面。
    广告很萌的

    回到我们之前的数据库字段设计,我们知道 parentid 可以和 id 字段结合来输出无限级分类的输出,还能用来表示节点间的关系。

    这种设计用得很普遍,而且是最省存储空间,但是却不是最有效率的。比如现在我们有这么一个需求,需要查询指定深度节点时就会遇到问题。因为是采用递归(递归的效率你懂的)的方法,我们需要通过递归来逐层展开才能获取到所有该层的节点,然后再在其中进行查询实在既浪费时间又浪费空间。那么有没有更好的做法呢?

    现在再来看看我的设计,增加了两个字段: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
    

    换作用递归来实现,就可能没那么高效,而且也没有这么直观。这样做的道理就在于,通过增加冗余信息来提高检索速度,同时这些冗余信息非常容易维护所以不容易因为操作不慎而导致信息不一致。

    当然我的设计并不完善,上面仅仅只谈了益处,如果你觉得这个设计不好,也可以只使用普遍使用的递归方式。

更多 推荐条目

Welcome to NowaMagic Academy!

现代魔法 推荐于 2013-02-27 10:23   

本章最新发布
随机专题
  1. [移动开发] 刷机与root相关 2 个条目
  2. [PHP程序设计] PHP数组的遍历 7 个条目
  3. [软件工程与项目管理] 开始使用Git 3 个条目
  4. [PHP程序设计] 对输入文件类型的检测 1 个条目
  5. [PHP程序设计] PHP与Stream流 5 个条目
  6. [Python程序设计] Django Web环境配置 2 个条目
  7. [智力开发与知识管理] 超越整体性学习 5 个条目
  8. [移动开发] Android Studio里的Gradle 3 个条目
  9. [移动开发] Android布局基本知识 3 个条目
  10. [移动开发] Layout_weight属性解析 5 个条目
  11. [移动开发] Content Provider内容提供者 3 个条目
  12. [C语言程序设计] 结构体基本知识 1 个条目
窗口 -- [八点]