sqlite3树形结构遍历效率对照測试

一、缘起

项目数据结构:本人从事安防行业,视频监控领域。项目中会遇到监控点位的组织机构划分、暂时划分的巡逻点位等。这些相机点位、连同组织机构,它们在逻辑关系上构成了一个树形结构。

又因为不论什么一个点位属于一个组织机构,也可能属于一个被暂时创建的视频巡逻计划中,因此,能够看出,不论什么一个节点,包含相机节点和组织机构节点,都有可能有至少一个父级节点,且不论什么一个组织机构节点也会有多个下级子节点。这中逻辑关系又构成了图。

数据量规模:一个市级别的管理平台,点位数量在十万至几十万级别。一个省级别的管理平台,所接入的点位规模在百万级别。

问题:监控平台常常须要用到的功能,就是要高速查询出来一个节点下的全部子节点、子节点的子节点等的树形结构。


我们的数据库眼下採用的是sqlite3。
眼下须要对查询遍历部分做性能上的优化,由我来承担完毕这项工作。本人无数据库方面开发的经历。仅仅用了一天时间尝试了例如以下4种方案。或许还有最好的。亲爱的读者您看到了这篇帖子,假如知道有更好的方法,还请赐教,笔者不胜感激。

因为一些原因。在这里不便于公开各个方案的代码、sql语句、或sqlite表结构等信息。还请谅解。

二、方案

从上面的数据结构能够看出,要想查询到一个节点的全部子节点,通常的做法是必须使用递归的方法。这就有了方案1、2、3。假设转换一下思路。则就产生方案4。


方案1:multimap递归查询
因为每一个节点极其父节点构成一个pair,这恰巧和STL中的multimap的数据模型一致。所以自然考虑到使用multimap实现递归遍历的方案。

详细例如以下:

(1)从数据库中查询全部的数据。
(2)将查询的结果集插入(insert)到multimap中。

(3)用递归的方法遍历查询到multimap中的节点及全部树形子节点。


方案2:函数递归查询
方案1是将全部数据都查询出来,然后在multimap中递归查找。方案2的思路是。查找这个节点的子节点,然后查找子节点的子节点,然后查找子节点的子节点的子节点......(子子孙孙无穷匮也)。实现方法是编写一个递归函数,递归地查询数据库,即递归地select。
(1)从数据库中查询全部的父节点是“传入节点”的节点记录。
(2)从(1)中的结果集中,取出查询到的节点id,将这个节点作为“父节点”,然后又一次运行(1)。
(3)由(1)和(2),假设某一次遍历的结果集为空。则表示当前遍历到的这个节点是叶子节点,它没有子节点了。

则递归函数退出。


方案3:sql语句递归查询

方案1、2的思路都是在sql语句之外递归查询。

假设可以写出递归的sql语句,效果是不是能更好呢?于是有了方案3。简单来说。方案3是将方案2中用函数实现的"查找子节点的子节点的子节点......"。替换为用sql语句来实现。

关于sqlite3的递归语句,请參考我的另外一篇博文《sqlite3-递归查询》。

这里要注意一下,sqlite3的递归语法 with recursive 可能在 其3.7.X 及下面版本号不受支持,可能会提示语法错误syntax
error
。我的sqlite3库升级到3.8.x之后就能查询到结果了。

方案4:引入关系表

如今数据库表的结构例如以下图所看到的。

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

它是一种结构化的数据库表结构

将节点的id和父节点id都存储在一个记录中。

优点是开发时候高速。坏处是,不便于扩展和改动。

说它不便于扩展,是由于假如一个节点有两个父节点。则一个字段无法满足。再加一个father_id字段吗?显然不现实,由于不知道会有多少个父节点。

说它不便于改动,是由于。假设将多个父节点id都採用格式化都填入father_id字段。则在维护记录的时候会带来“拼串和解析串”的步骤,带来维护上的麻烦。

那么。能否够换一种思路,採用面向对象的思维创建数据库表呢?于是想到了以下的表结构和表关系。

如图所看到的。添加一个关系表,专门用来存储节点之间的关系。

将father_id和son_id作为联合主键。

如此一来,节点与节点之间的关系,事实上就相应的是关系表中的一条记录!一个节点有多少个子节点,关系表中就有多少条记录。一个节点有多少个父节点。也是这样。

这样改造了数据库表之后。带来的优点是显而易见的。

首先是可维护性的提升。

从曾经的解析改动表字段,到如今的插入删除一条或多条记录。

其次是开发维护人员对于数据的关系也会理解地更加深刻和清楚。

但不可避免,也有不足之处。

首先是开发的成本。这种表结构和表关系。不利于高速开发。

其次是如今的软件系统已经用了好几年。突然改动,可能会造成现场维护上的压力突然增大。

第三,这种结构。是否满足业务功能要求的效能,还是个未知数。

三、结果对照

以下给出上述方案1、2、3的測试对照表。

方案1

方案2

方案3

从理论上来讲。查询得到结果的效率是 方案3 > 方案1 > 方案2。

从上面3个表来看,结果的确如期望的那样。

可是,有些意外的是。方案3中从结果集中获取下一条记录这一步骤(即next),太占用时间,居然达到了97%的占比。

从综合效率上来看,方案1时间最快。其次是方案3,最慢的是方案2。

由于方案2要运行大量的函数递归调用。函数栈切换。这是最为耗时的。

sqlite3树形结构遍历效率对照測试的更多相关文章

  1. 海量数据插入数据库效率对照測试 ---ADO.NET下SqlBulkCopy()对照LINQ 下InsertAllOnSubmit()

    摘要:使用.NET相关技术向数据库中插入海量数据是经常使用操作.本文对照ADO.NET和LINQ两种技术.分别使用SqlBulkCopy()和InsertAllOnSubmit()方法进行操作. 得出 ...

  2. 香蕉派路由功Openwrt、Android功耗对照測试

    路由这个东西是要长期通电使用的,所以功耗也是须要关注的.如今香蕉派路由已经有了openwrt和android两个 系统,这两个系统的功耗是否一样呢? 測试工具:QUIGG的德国产功耗測试仪一个.手机充 ...

  3. Swift,Objective-C语言性能对照測试

    原文发表于踏得网 Swift包括了非常多现代语言特性尤其是从一些脚本语言如Javascript/Ruby中汲取了营养. 此外苹果公布Swift时,使用特别选用的一些样例来宣称Swift性能对于Ojbe ...

  4. Android性能測试 一些适用于Android Studio的代码审查和性能測试工具

    导言: Android应用在CPU占用,内存消耗方面的性能指标是影响产品质量的重要因素,因为QQ管家,360手机助手等应用都提供直观的内存消耗,流量监控功能,致使用户比以往更加关注软件的性能,并以此进 ...

  5. 车牌识别--S5PV210測试第二次优化

    优化: 1.RGB转HSV 浮点运算改成定点运算: 2.匹配模板由图片改成C语言数组: 3.优化測试BMP车牌图片读取(两层for循环改为一层for循环). 总体相比优化之前时间降低110ms左右. ...

  6. 測试之路3——对照XML文件2

    距离上一篇对照xml文件隔了非常久,并不代表一直做了那么久. 事实上上一次对照xml文件一直出错,事实上我忽略了一个非常easy的问题:我从根文件夹下得到的全部孩子,是这个根下的,而xml文件的组织形 ...

  7. iOS自己主动化測试的那些干货

    前言 假设有測试大佬发现内容不正确.欢迎指正,我会及时改动. 大多数的iOS App(没有持续集成)迭代流程是这种 也就是说.測试是公布之前的最后一道关卡.假设bug不能在測试中发现,那么bug 就会 ...

  8. PHP归档phar性能測试

    PHP自从5.3后新增PHAR归档,Phar 归档的概念来自 Java™ 技术的 JAR 归档,它同意使用单个文件打包应用程序.这个文件里包括运行应用程序所需的全部东西.该文件不同于单个可运行文件,后 ...

  9. YbSoftwareFactory 代码生成插件【十八】:树形结构下的查询排序的数据库设计

    树形结构的排序在中国特色下十分普遍也非常重要,例如常说的五大班子,党委>人大>政府>政协>纪委,每个班子下还有部门,岗位,人员,最终排列的顺序通常需要按权力大小.重要性等进行排 ...

随机推荐

  1. indeed 5.13 第二次网测

    题目描述,我找不见了,大概写一下想法和代码吧. 1. 没有看 2. 由于数据范围很小,就是简单的枚举,求全排列,然后更新答案. #include<bits/stdc++.h> #defin ...

  2. Java导入excel并保存到数据库

    首先建立好excel表格,并对应excel表格创建数据库表. 前台jsp页面:其中包含js <%@ page language="java" import="jav ...

  3. linux ssh 经常断开 的解决方法

    1.现象 在linux ,用ssh进行远程连接时,经常会发生长时间后断线,或者是无响应,就像卡住的感觉(键盘输入不进去). 2.解决方法 在ssh客户端的linux设置 # sudo vim /etc ...

  4. vue axios 请求带token设置

    API axios.js import axios from "axios"; let AUTH_TOKEN=(function(){ return localStorage.ge ...

  5. PCL: 根据几何规则的曲面剖分-贪婪法表面重建三角网格

    点云场景中进行物体识别,使用全局特征的方法严重依赖于点云分割,难以适应杂乱场景.使用局部特征,即对点云进行提取类似于3D SURF.ROPS之类的局部特征,需要寻找离散点云块的局部显著性. 点云的基本 ...

  6. NDK 使用STL

    参考链接:Android中使用STL 1. 在 Application.mk 中添加代码"APP_STL:= gnustl_static"后, 文件中的内容如下: APP_ABI ...

  7. day002 计算机基础之 操作系统和编程语言的分类

    &nbsp&nbsp&nbsp&nbsp&nbsp&nbsp今天主要针对计算机基础中的操作系统和编程语言的分类进行了讲解. 操作系统 &nbsp ...

  8. Office 2013 提示找不到 Office.zh-cn\XXXXX

    1.先卸载Office 2013(已经卸载了的无视这一步)2.卸载Office 2013 后把C:\ProgramData\Microsoft\OFFICE文件删掉.3.删除下列注册信息1).依次点击 ...

  9. Day 18 hashlib,logging模块

    hashlib 模块 作用:hash是一种算法,主要提供SHA1,SHA224,SHA256,SHA384,SHA512,MD5算法,该算法接受传入的内容,经过运算得到一串hash值 特点: 1.只要 ...

  10. 关于js开发中保留小数位计算函数(以向上取整或向下取整的方式保留小数)

    前端工作中经常遇到数字计算保留小数问题,由于不是四舍五入的方式不能使用toFixed函数,本文采用正则表达式匹配字符串的方式,解决对数字的向上或向下保留小数问题: 1.向上保留小数(只要目标小数位后有 ...