MySQL递归查询——数据平坦化新思维
来源:互联网 发布:美国人饮食 知乎 编辑:程序博客网 时间:2024/06/07 17:38
最近在做Oracle到MySQL的数据库的移植过程。两者之间的诸多差别(比如MySQL不支持ADO、函数不一致、唯一索引限制不一样等等)都易于解决,但有一个问题却困扰我们良久:Oracle的递归查询(select... from ... start with ... connect by ... where...子句)在MySQL中不受支持。
在SQL Server2000(2005已经支持递归查询)和DB2中,都可以使用存储过程的方式,在存储过程中完成对数据库的递归检索,并返回记录集的方式实现;但是MySQL数据库可以用存储过程完成递归,但存储过程本身不能返回临时的记录集。
首先,最先想到的是采用临时表的方案解决(网上很多大哥都用的这种方案),但做了一个效率测试,在10w条数据中使用临时表递归检索,1分钟过去了,5分钟过去了,10分钟过去了,半小时过去了……没有返回(后边测试了500条数据需要接近8秒钟时间)。临时表方案效率肯定是有问题的。
然后,公司的DB大佬支招了:使用一个字符串字段(称为“编码”,字段名称比如命名为innerID)来表示记录的父子关系。核心思想是为需要递归的表添加三个字段(摘录自同事的设计文档):
- 节点编码:为当前记录行的编码(内部编码),它的所有直接下级记录行的编码都是以他为依据进行扩展,他的所有直接下级记录行的上级编码为这个值。
- 上级编码:为上级记录行对应的编码,这是查询某个节点的下属节点或者下下属节点的依据。
- 最后编码:为目前分配到最后一个下级记录行的编码,为增加下一个下级记录行提供快速计算的依据。
各个记录行的“编码”如下图所示。
这种方案的确可以很好的解决查询某行下所有子行的符合条件的记录集的问题。只需要形如SELECT * FROM xxx WHEREinnerID LIKE "A0ZZ%" [AND othercondition]的查询条件即可检索出A0ZZ记录及其所有下属节点的符合条件的记录集。
但是,导致了另外一个问题的产生:当对某个父记录集节点(特别是位于根节点下的二级节点)进行移动位置时,将会是致命的(需要修改所有的innerID,并且如果要考虑文件夹的合并的话,那将更加复杂),如果还要考虑多终端的并发性问题,会出现的问题将非常复杂。
所以,这个方案可以作为备选方案(需要在我们的产品SPEC中加入一些Limitation),但最好能找到更好的解决方案。
最好,在我们同事的不懈努力下,在MySQL的论坛中找到了一种更加合理的方案。
其实,这个方案我们也应该早就可以想到,特别是在倡导“扁平化管理”的今天。它的核心思想就是将递归所实现的层级化结构,使用数字按照嵌套的思路实现扁平化,截图(来自原网页):
(层级化结构)
(转化为嵌套后的平坦化结构)
具体方案可以参考原始网页:http://dev.mysql.com/tech-resources/articles/hierarchical-data.html
使用这种方案,相比于前一个方案,一方面在查询的时候可以省掉字符串的LIKE关键字,有助于提升效率;另外一方面,在对数据集进行修改时,也只需要对增加的左值和右值节点,进行批量的UPDATE(增加一定的数字或者减少一定的数字,但效率需要测试),不需要更复杂的逻辑,在并发性上也可以处理得更好。
总结:其实扁平化不光是在管理上,也可以在技术中,MySQL的递归查询只是一个简单的例子,我们在开发过程中,如果能够换个角度想问题,也许可以有更多更好的解决方案。
- MySQL递归查询——数据平坦化新思维
- MySQL递归查询——数据平坦化新思维
- 《爆发——大数据时代预见未来的新思维》
- mysql 中的数据实现递归查询
- 大数据,新思维
- 递归查询—写法
- mysql递归查询
- Mysql递归查询
- MySQL递归层次查询
- MySql递归层次查询
- mysql递归查询。
- MySql递归查询函数
- Mysql递归查询
- mySql递归查询函数
- mysql递归查询
- MySQL递归查询
- mysql递归查询
- mybatis+mysql递归查询
- android上的i-jetty (1)环境搭建
- ORA-12712: new character set must be a superset of old character set
- 通过TEB/PEB枚举当前进程空间中用户模块列表
- html-中文字体在CSS中的显示(Unicode编码)
- linux 拷贝文件(本机内和机器之间)
- MySQL递归查询——数据平坦化新思维
- socket问题集合(待完善)
- android上的i-jetty (2)用Servlet显示Android设备的app列表
- Linux(CentOS 6.2)系统上安装Mplayer播放器
- 中断
- HashMap和Hashtable的区别
- 设置IIS,使其可以下载某种类型的文件而不是打开
- LUPA开源社区 源码之家
- Mime 类型列表