一种基于golang解决分库分表下检索排序和分页问题的优化方法与流程



1.本发明属于互联网数据处理技术领域,涉及一种基于golang 解决分库分表下检索排序和分页问题的优化方法。


背景技术:

2.在数据量动则上百万条的业务场景下,横向分库分表是解决单体数据库容量不足的一种方法。但这也造成了检索排序分页的困难。由于分库分表,无法拥有全局视野对符合条件的记录精准完整检索以及排序和分页,这对需要检索分页和排序的应用带来极大的困扰。
3.目前与本发明最相似的一种方案,就是将所有库中所有表进行一次足够大范围的检索后,合并所有记录,形成检索结果视图,再对该视图进行排序,进而完成分页。亦或者在分库分表时进行业务方向收敛,对表范围进行限制,通过该范围匹配检索条件,以达到缩小检索范围,进而合并记录,来完成最终的排序分页。
4.目前的技术缺点,查询数据量会随着页码数的增大,对内存的占有量和cpu计算量达到平方级的增长,这是不适合大多数技术支撑的。此外,若增加对数据库分库分表的数据在范围划分策略上的业务性限制,会导致部分数据库处于冷机状态,另一部分处于热点区域长期被检索,造成检索瓶颈。
5.本发明通过对数据散落规则分析,二次查询收敛,有效缩小待检索范围,同时又保证数据查询、分页的准确精度,达到有效缩减数据查询量,进而减少对系统内存的占有和计算力,从而完成对数据库分库分表的数据的检索排序分页操作的优化,也是对算法复杂度和时间复杂度上的双重减负。


技术实现要素:

6.本发明的目的是针对现有的技术存在上述问题,提出了一种基于golang解决分库分表下检索排序和分页问题的优化方法,在数据分库分表的情况下,通过该优化方法实现全库内任意字段的精确检索以达到精确排序和分页目的。
7.本发明的目的可通过下列技术方案来实现:
8.一种基于golang解决分库分表下检索排序和分页问题的优化方法,其特征在于,包括以下步骤:
9.s1、构建golang服务作为中间件,要求可以独立启动;
10.s2、启动golang中间件,拦截并解析应用程序发送的查询指令,根据采用分表算法的分库分表规则,对查询指令进行分析;
11.s3、将分析后的查询指令发往后端的数据库,后端进行处理后得到第一次查询结果;
12.s4、根据对第一次查询结果的分析,得到第二次查询条件;
13.s5、通过对第二次查询条件的处理,得到第二次查询结果;
14.s6、将第二次查询结果经过精确排序和分页后,发送给应用程序对应的用户。
15.所述查询指令包括,输入要查询的数据要求,数据要求由sql 语句构建,对数据要求的查询范围和数据库中的数据落盘规则进行分析,并使用golang语言的协程,并行查询所有的数据库表。
16.所述算法包括哈希分表算法、自然月分表算法、日期分表算法及范围分表算法。
17.所述分库分表规则包括表与库的映射关系、分表的数量、表的拆分规则。
18.所述对查询指令进行分析的分析方法包括分片分析、路由分析。
19.所述第一次查询结果包括前部数据、目标数据和尾部数据,目标数据为用户所实际需要的数据,前部数据和目标数据均为有效数据,尾部数据为无效数据。
20.所述对第一次查询结果的分析如下:显示每个数据库表中是否至少有两个存在有效数据,如有,则得到第二次查询条件;如无,则本次查询结果为最终查询结果,并对唯一存在有效数据的数据库表进行精确查询后并统计分析,得到确定的目标数据,并对目标数据精确排序和分页后,发送给应用程序对应的用户。
21.所述对第二次查询条件的处理如下:对每个数据库表中的有效数据量进行统计,存在有效数据量的数据库表为有效集,不存在有效数据量的数据库表为空集,其中含有最少有效数据量的数据库表,以其存在的有效数据量为头部数据量,将空集本应含有的头部数据量分配到其他有效集中,重新进行检索,即可完成覆盖目标数据和减少数据返回量,得到第二次查询结果。
22.根据本发明,提供了一种计算机设备,包括处理器、存储器以及存储在存储器中且被配置为由处理器执行的计算机程序,其特征在于,所述处理器执行所述程序时实现上述方法。
23.根据本发明,提供了一种计算机可读存储介质,所述计算机可读存储介质存储有计算机程序,其特征在于,所述计算机程序被处理器执行时执行上述方法。
24.与现有技术相比,本基于golang解决分库分表下检索排序和分页问题的优化方法具有以下优点:
25.1、采用二次查询,第二次查询范围依托第一次查询结果,第一次查询条件依托数据分析。
26.2、使用golang语言的协程特写,并行执行查询,增加查询效率和计算速度。
27.3、有效分析数据落盘特性,以及无数据损失缩减查询范围。
附图说明
28.图1是本发明实施例中理想状态下每个数据库表均匀分布的数据量图。
29.图2是本发明实施例中实际状态下数据落盘存在差异的数据量图。
30.图3是本发明实施例中划定数据分割线的数据量图。
31.图4是本发明实施例中无法覆盖目标数据的数据量图。
32.图5是本发明实施例中无法覆盖目标数据的数据量图。
33.图6是本发明实施例中无法覆盖目标数据的数据量图。
34.图7是本发明实施例中无法覆盖目标数据的数据量图。
35.图8是本发明的原理框图。
36.图9是本发明中计算机设备的结构示意图。
具体实施方式
37.以下是本发明的具体实施例并结合附图,对本发明的技术方案作进一步的描述,但本发明并不限于这些实施例。
38.场景设定:某个应用新闻数据量在百万级,该数据分布在10 台数据库中,并做了随机散列,可视为单台数据库表中存储约10 万条数据。现有需求从所有新闻中找出编辑者张三按发表文章时间顺序正序的第10页新闻,每页新闻量为100条,即查找张三发表的第901条至第1000条数据。
39.对比例:
40.目前直接解决方案就是,向10台数据库中分别发送类似域“select*from news where uername=

张三’orderby timeasc”,得到每个库表里所有张三的发表过的新闻,进而将所有数据进行融合排序,找出第901-1000条的数据进行返回,但是这将会造成内存性能的急剧下降,为了查找某人的100条数据,需要将该人的数据全部查找出,这里做一个极端假设,若所有新闻都是该编辑发表,相当于将所有新闻都读取进来,首先这种读取方式就不现实,会导致服务器直接宕机,而且这相当于未采用分库分表。再退一步讲,假设数据量没那么大,服务器可以读取进来这些数据,接下来对数据的融合,查找排序,都将是对cpu算力的极大考验。
41.本实施例:
42.本方案对查询范围和数据落盘规则进行分析,有效缩减查询数据量,并使用golang语言的协程,并行查询所有的数据库表,缩小数据量的同时,更缩短了查询时间,有效的减少时间复杂度。
43.具体方案如下:
44.分析要查询的数据要求,查找的是张三发表的第901至1000 条数据,这100条数据散落到10台数据库表中,具体每条数据在哪个数据库表中暂不得知。
45.我们在不影响结果的情况下,简化一下场景,假设数据库表里的所有数据都是张三所为,我们考虑前1000条数据情况,把这 1000条数据按顺序随机放入10个表中,也就是说,每个表中平均只需要查找100条数据即可基本覆盖前1000条数据,现在我们找到一个大约的范围,还不是很准确,因为会存在某个库会漏掉目标数据的极端情况,也就是说有可能获取到1000条之后的数据,那有没有办法解决这个问题呢?
46.当然,我们的目标数据是901-1000条数据,前900条数据分散在10台数据库表中,也就是说理论上每台数据库表的前部数据在我们并不需要的前900条数据内。那么我们把这100条的搜索范围从开始的第一条数据相对的后移,直至能完全覆盖掉大部分目标数据,这样每个库表中目标数据理论上都会被我们的检索范围所包含,那我们相对后移多少合适呢?
47.我们来分析一下,第901条数据散落哪个表中我们不知道,既然我们知道前900条数据不是我们想要的,而这900条数据分别散落到10个库表中,平均每个库表有90条数据是我们不想要的,并且他们的总数是一定,也就是一个库中数据多了,另一个库中必然会少,
是一个此消彼长的过程。
48.所以理想情况下,如图1,我们可以找第90条数据作为分界线,这样每个库往后的100条数据是大概率包含全部目标数据的,说大概率只是相比于之前范围更准确。
49.但实际状态下,数据真实落盘是不那么均匀的,如图2,那么这个90的分界线还有意义么?
50.有,当然有!我们看一下图3,部分目标数据在水平线之上,部分在水平线之下。
51.接下来的思路有些绕,我们可以画个图辅助理解一下。每个柱状图代表一个库表,橘色部分是需要找出来的数据,蓝色和灰色是不需要的数据部分。我们同样以第90条数据为分界线,往后查 100条数据,之所以以100条为范围,是考虑这100条数据极端的落在某一个库表中,参考图4。图4这就又给了我们一个提醒,包含另一种极端情况,某个库表中不存在前部数据和目标数据,只存在尾部数据的情况。这样我们有可能在第10台数据库中 90-100条数据压根无法覆盖目标数据,所以我们要对极端情况做兼容处理。可以预见的是,每个数据库表查询结果就是要么有数据要么没有数据,这两种结果将带来两种不同的结果。若某一台数据库没有返回任何数据,也就是说,该库表是空的,可以理解为,原本属于该库表中的90+100条数据,被分散到其他数据库表中,至于在哪个库表我们不得而知,因此,每当某个库表中返回一个空数据集时,我们理应增加190条的查找范围。一般情况下,有n(n《10)台数据库表返回了空集,那么我们在有数据返回的数据库中再次查找的范围右区间范围应该是(100+190*n),左区间应该是这5台数据库表中返回集合的最小数据项即min(集合1,2,3,4,5),更极端的情况下,是只有1台数据库表返回了结果集,这也就意味着,其他9台没有数据,这1000条数据都在一台数据库表中,因此可以做优化,直接查询901-1000条数据,相比与查询91-1810条数据,效率更优,但也反向证明了这个区间范围是能准确将所有目标数据都能包含在一起,且又避免完全查询所有数据的问题。
52.所以综上考虑,我们需要找到一个合适的查找范围,这个查找范围依据首次查询结果来定,通过查询每个库表中90-190的数据,判别是否至少有两个数据集返回,若只有一个,则执行901-1000 条的精确查询,若大于1个集合,可以通过对比找到一个最小的数据项,我们以此为数据范围头部,然后尾部数据以91+190*n(其中 n是返回空数据结果集的数据表个数),进而形成p(首部节点,尾部节点)区域,通过对10台数据库的二次区域查询,即可完成覆盖目标数据和减少数据返回量,再综合golang的协程优势,分组计算,每个数据库表返回数据的首部增量,对比第一次查询偏移数90,计算出当前第一个数据的偏移位置,累计计算出最小数据的在全局视野上的偏移,从而组合出901-1000条数据。
53.本方案为检索查询优化方案,为数据库中间件算法的一部分,可完成分库分表的数据查询检索分页功能。
54.本发明充分发挥数据分析作用,参考二分法思想,用逻辑思考做到无数据损失缩减查询范围,折中算法复杂度,减少时间复杂度,有效提高数据响应速度。
55.本文中所描述的具体实施例仅仅是对本发明精神作举例说明。本发明所属技术领域的技术人员可以对所描述的具体实施例做各种各样的修改或补充或采用类似的方式替代,但并不会偏离本发明的精神或者超越所附权利要求书所定义的范围。