1、树形结构应用场景

有时我们需要保存一些树形的数据,比如组织架构、话题讨论、知识管理、商品分类等,这些数据之间存在一种递归关系,很多开发人员想到的第一个解决方案往往是记录每个节点的父节点,例如以下的评论表。

CREATE TABLE comments (

comment_id int(10)  NOT NULL,

parent_id int(10)  DEFAULT NULL,

comment text  NOT NULL,

PRIMARY KEY (comment_id)

) ENGINE=InnoDB DEFAULT CHARSET=utf8

采用这样的结构,就需要编写复杂的代码递归检索很多记录,查询的效率就会很低。如果数据量不大、讨论内容相对固定,数据的层次较少,那么采用这样的结构就会是简单的、清晰的,这种情况下此结构还是合适的;但如果数据量很大,查询就会变得很复杂。下面介绍两种更通用,扩展性更好的解决方案:路径枚举和闭包表。

2、路径枚举(增加一个字段存储所有父级节点信息,用特殊符号分割开)

基于上面的表结构,可以增加一个字段path,用于记录节点的所有祖先信息。记录的方式是把所有的祖先信息组织成一个字符串。

因为路径(path)字段包含了该节点的所有祖先信息,所以可以轻易地获取某个节点的所有祖先节点,可以用程序先获取path字符串,然后再使用切割字符串的函数处理得到所有的祖先节点。

如果要查找某个节点的所有后代,例如查找comment_id等于3的所有后代,可以使用如下的查询语句。

SELECT * FROM comments WHERE path LIKE ‘1/3/_%’;

如果要查找下一层子节点,可以使用如下的查询语句

SELECT * FROM comments WHERE path REGEXP “^1/3/[0-9]+/$”;

插入操作也比较简单,只需要复制一份父节点的路径,并将新节点的ID值(comment_id)添加到路径末尾就可以了。

枚举路径的方式使得查询子树和祖先都变得更加简单,查看分隔符即可知道节点的层次,虽然冗余存储了一些数据,应用程序需要额外增加代码以确保路径信息的正确性,但这种设计的扩展性更好,更能适应未来数据的不断增长。表5-2中,仍然保留了parent_id列,是为了使一些操作更加方便,也可以用来校验路径信息是否正确。

3、闭包表(增加一张父子节点关联关系表)

闭包表也是一种通用的方案,它需要额外增加一张表,用于记录节点之间的关系。它不仅记录了节点之间的父子关系,也记录了树中所有节点之间的关系。

使用如下命令语句新建表path

CREATE TABLE path (

ancestor int(11) NOT NULL,

descendant int(11) NOT NULL,

PRIMARY KEY (ancestor,descendant)

) ENGINE=InnoDB DEFAULT CHARSET=utf8

ancestor表示祖先,descendant表示后代,存储的是comment_id值。

如果要统计comment_id等于3的所有后代(不包括其自身),可以直接搜索path表祖先是3的记录即可得到,查询语句如下:

SELECT COUNT(*) FROM path WHERE ancestor=3 AND descendant <> 3;

为了更方便地查询直接父节点/子节点,可以增加一个path_length字段以表示深度,节点的自我引用path_length等于0,到它的直接子节点的path_length等于1,再下一层为2,以此类推。

如上所述的数据结构,新增了一个表,用于存储节点之间的信息,是一种典型的“以空间换时间”的方案,而且一个节点可以属于多棵树。相对于路径枚举,闭包表的节点关系更容易维护。

文章基于MySQL DBA修炼之道整理,版权属于原作者

MySQL存储树形数据优化技笔记相关推荐

  1. mysql树形结构的效率_MySQL存储树形数据优化技笔记

    1.树形结构应用场景 有时我们需要保存一些树形的数据,比如组织架构.话题讨论.知识管理.商品分类等,这些数据之间存在一种递归关系,很多开发人员想到的第一个解决方案往往是记录每个节点的父节点,例如以下的 ...

  2. 分布式日志sleuth+分布式追踪系统zipkin+消息中间件rabbitMQ+MySQL存储跟踪数据

    一.了解分布式架构下系统的监控问题 接口监控问题 监测性能瓶颈 解决方案:Sleuth 日志监控问题 日志分散 解决方案:ELK+Kafka 二.使用Sleuth实现大觅网微服务跟踪 1.打开一个分布 ...

  3. mysql 存储树形结构

    像mysql这样的关系型数据库,比较适合存储一些类似表格的扁平化数据,但是遇到像树形结构这样有深度的人,就很难驾驭了. 举个栗子:现在有一个要存储一下公司的人员结构,大致层次结构如下: (画个图真不容 ...

  4. 文档型数据库设计模式-如何存储树形数据

    在数据库中存储树形结构的数据,这是一个非常普遍的需求,典型的比如论坛系统的版块关系.在传统的关系型数据库中,就已经产生了各种解决方案. 此文以存储树形结构数据为需求,分别描述了利用关系型数据库和文档型 ...

  5. mysql存储netcdf数据_关于NetCDF与HDF5存储科学数据的观点?

    任何人有足够的经验w / NetCDF和HDF5,给他们一些关于他们作为一种存储科学数据的方法的利弊/ minus? 我使用HDF5,并希望通过Java读/写,但接口本质上是C库的包装,我发现混乱,所 ...

  6. mysql 查找相似数据_MySQL学习笔记之索引

    索引是存储引擎用于快速找到记录的一种数据结构. 索引对于良好的性能非常关键.尤其是当表中的数据量越来越大时,索引对性能的影响愈发重要.在数据量较小且负载较低时,不恰当的索引对性能的影响可能还不明显,但 ...

  7. MySQL两千万数据优化迁移

    最近有一张2000W条记录的数据表需要优化和迁移.2000W数据对于MySQL来说很尴尬,因为合理的创建索引速度还是挺快的,再怎么优化速度也得不到多大提升.不过这些数据有大量的冗余字段和错误信息,极不 ...

  8. mysql存储引擎 索引优化_MySQL存储引擎,索引及基本优化策略

    存储引擎 与Oracle, SQL Server这些数据库不同,MySQL提供了多种存储引擎.什么是存储引擎?存储引擎其实就是一套对于数据如何存储,查询,更新,建立索引等接口的实现.不同存储引擎特性有 ...

  9. C++ MySQL存储二进制数据、存储照片

    版权声明:本文为CSDN博主「intfre」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明. 原文链接:https://blog.csdn.net/nibiru_ho ...

最新文章

  1. linux 网络管理器未运行怎么解决,Ubuntu下提示网络管理器未运行解决方法
  2. python断言assert实例_Python断言assert的用法代码解析
  3. 一个特殊的事件绑定程序(通用于各种浏览器)
  4. python 去除txt文本内容重复值
  5. c# xaml语言教程,Xamarin XAML语言教程XAML文件结构与解析XAML
  6. 目标跟踪之MOSSE算法(C++版本配置及原理简介)
  7. MyBatis mysql 字符串拼接
  8. python 计算均值、方差、标准差 Numpy,Pandas
  9. 20几岁要懂点经济学【笔记】
  10. Http——超文本传输协议
  11. 关于系统分析师的考试感想
  12. IE中点击链接下载EXCEL文件直接以乱码方式打开解决
  13. 解读72篇DeepMind深度强化学习论文
  14. 基于winform(C#)的飞鸟小游戏
  15. Kendo UI 刷新数据源信息
  16. 大数除法——超详细讲解
  17. 会话及会话技术、Cookie对象、Session对象 详解
  18. AGV与电梯交互系统设计
  19. 草图大师怎么取消组件关联_草图大师隐藏其他组件快捷键是什么?
  20. 如何做一个股票自动交易系统的步骤

热门文章

  1. .Net开发环境配置[OS/IIS/VS...]
  2. 语音交互设备 前端信号处理技术和语音交互过程介绍
  3. html期末网页设计,求网页设计的期末作业一份 HTML的
  4. boost解析xml文件
  5. android自定义画板,android 自定义控件 -- 画板
  6. matlab中求三维中的多个体积,用matlab计算由下面2个几何体围成的体积: x^2+y^2+z^2=36,((x-4)/5)^2+((y-1)/3)^2+((z-2)/5)^2=1...
  7. suse 内核编译安装_升级SUSE Linux内核的完整步骤!
  8. python 逐行读取csv_在R中如何逐行读取CSV文件并将内容识别为正确的数据类型?...
  9. 网口扫盲二:Mac与Phy组成原理的简单分析(转)
  10. .net 技术类网址