热门标签 | HotTags
当前位置:  开发笔记 > 数据库 > 正文

查询性能“逆袭”—巧用“BETWEEN”

查询性能逆袭巧用BETWEEN一、问题的背景有若干个表(暂且认为4个表),这几个表的主要字段一致,即有若干个公共的字段,其中ID具有唯一性,并且四个表中唯一,类型为String.。如下面所示:table1(ID,Name,Type,CommonField1,CommonField12,Table1Ot

查询性能逆袭巧用BETWEEN 一、问题的背景 有若干个表(暂且认为4个表),这几个表的主要字段一致,即有若干个公共的字段,其中ID具有唯一性,并且四个表中唯一,类型为String.。如下面所示: table1(ID,Name,Type,CommonField1,CommonField12,Table1Ot

查询性能“逆袭”—巧用“BETWEEN”

一、问题的背景

有若干个表(暂且认为4个表),这几个表的主要字段一致,即有若干个公共的字段,其中ID具有唯一性,并且四个表中唯一,类型为String.。如下面所示:

table1(ID,Name,Type,CommonField1,CommonField12,……Table1OtherField1……)

table2(ID,Name,Type,CommonField1,CommonField12,……Table2OtherField1……)

table3(ID,Name,Type,CommonField1,CommonField12,……Table3OtherField1……)

table4(ID,Name,Type,CommonField1,CommonField12,……Table4OtherField1……)

至于这个表为什么设计成这样,是否达到基本范式?这个问题这里暂时不考虑,可以简单的认为这四个表存储了四类非常类似的数据。上级系统有这样的查询需求,暂且叫分页查询,类似一个Session的概念:

1、 需要查询的时候会发一个创建查询的消息,里面带了查询条件,并且说明了每次查询返回的数量。

2、 应答创建查询的消息中要返回符合查询结果的总数目,并且返回第一页数据。当然如果满足结果的数目小于每次查询的数据,直接将满足的结果返回。

3、 如果满足结果的总量大于每次查询的数量,即需要分页查询,那么,上级系统会发查询消息来查询第二页、第三页……依次类推,直至查完。

4、 查询完毕后,上级系统会发送一个删除查询的消息。

上面的查询条件是非常复杂的,没有使用类似SQL的语法解析,而是通过一个数据结构和查询文档描述。

具体例子说明:假如上级系统发一个创建查询的消息,假定总共有10万数据,每次查询为1000条,查询实现端收到该报文后,解析查询条件,查询得到有4999条满足查询条件的数据,那么第一次返回的报文中返回前1000条,并且注明满足条件的总数为4999。接着上级系统会发送查询消息,指定查询第二个1000条,依次查询,直到查到最后的999条,上级系统再发一个删除查询表示查询结束。对上级查询者而言,表的数量对其而言是透明的,默认就是这几个表中查询。查询示意图如下:

二、解决问题的思路

1、 缓存查询结果:根据查询条件,一次性将查询结果缓存,在内存中分页返回查询结果。最大的问题是如果满足结果数量级大的情况下很容易OOM。

2、 缓存查询符合条件的ID:根据查询条件,创建查询的时候先查询到所有符合条件的ID,将ID分页,每次查询请求来的时候用ID去查询本次需要的数据。构造SQL需要有技巧。

3、 缓存查询条件:每次来查询的时候根据查询条件来查询到所有数据,然后根据要求返回某一页。每次要重复解析查询条件,处理起来十分麻烦,也存在数据的不一致性。

实际实现中采用了第二种方案(方案二的问题在方案三中同样存在),处理起来简单又方便。但是问题又出现了,如果在一个查询“会话”中,创建查询的时候查询得到4999个ID,然后分5次返回,每次返回的数据中都需要根据1000个ID查询得到这1000行数据,那么我们很自然的会想到用”sellect * form XXXwhere in(…..)”由于SQL语句的长度限制,1000个ID就要查几十次,4999数据的话总共要查近百次,如果数据上几十万的话,查询次数更是吓人,查询时间将大部分花在不停的执行SQL查询上。那怎么来绕开这个弯子?

三、减少SQL查询次数的思路

先看个例子,假如数据库中只有这样是个ID的数据【1,2,3,4,5,6,7,8,9,10】,如果要查询ID为【2,3,4,7,8,10】,那么是否可以有这样两种思路来组织SQL查询条件

1、 where id in(2,3,4,7,8,10);

2、 where id between ‘2’ and ‘4’ orbetween ‘7’ and ‘8’ or between ‘10’ and ‘10’

上面的第二种用between方式构建查询条件,SQL语句基本上可以用一个完成?最坏的情况(也是SQL语句最长的情况)也就是需要查询的数据是ID【1,3,5,7,9】的情况。在实际数量巨大的情况下几乎不会出现这样“最糟糕的情况”,一般需要查询的数据是连续的,因此基本上任何查询都可以用一个between搞定。而如果用第一种方式构造查询条件,那么势必需要查询多次。

四、实际处理

以上面的例子为例,如果总数是10万条,符合条件的是4999条,那么可以这么做:

1、 将所有的10万个ID取出来缓存在内存并进行排序。

2、 将4999个查询结果ID缓存进行排序。

3、 每次查询1000(最后一次是999)数据时根据这1000ID和全部的10万个ID关系,通过某个算法构建between条件(这个算法不再详述),最终构造一个SQL查询条(注意只是一个SQL),这样一次查询就可以得到这1000条数据。

上面的缓存ID的方案是可行的,一般不会产生OOM。结果就是几百次查询优化成了一个查询,查询性能直接逆袭!


推荐阅读
  • 1:有如下一段程序:packagea.b.c;publicclassTest{privatestaticinti0;publicintgetNext(){return ... [详细]
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • Søren Kierkegaard famously stated that life can only be understood in retrospect but must be lived moving forward. This perspective delves into the intricate relationship between our lived experiences and our reflections on them. ... [详细]
  • 本文详细介绍如何使用Python进行配置文件的读写操作,涵盖常见的配置文件格式(如INI、JSON、TOML和YAML),并提供具体的代码示例。 ... [详细]
  • 计算机网络复习:第五章 网络层控制平面
    本文探讨了网络层的控制平面,包括转发和路由选择的基本原理。转发在数据平面上实现,通过配置路由器中的转发表完成;而路由选择则在控制平面上进行,涉及路由器中路由表的配置与更新。此外,文章还介绍了ICMP协议、两种控制平面的实现方法、路由选择算法及其分类等内容。 ... [详细]
  • 本文将介绍如何使用 Go 语言编写和运行一个简单的“Hello, World!”程序。内容涵盖开发环境配置、代码结构解析及执行步骤。 ... [详细]
  • 线性Kalman滤波器在多自由度车辆悬架主动控制中的应用研究
    本文探讨了线性Kalman滤波器(LKF)在不同自由度(2、4、7)的车辆悬架系统中进行主动控制的应用。通过详细的仿真分析,展示了LKF在提升悬架性能方面的潜力,并总结了调参过程中的关键要点。 ... [详细]
  • 本文探讨了Hive中内部表和外部表的区别及其在HDFS上的路径映射,详细解释了两者的创建、加载及删除操作,并提供了查看表详细信息的方法。通过对比这两种表类型,帮助读者理解如何更好地管理和保护数据。 ... [详细]
  • C++实现经典排序算法
    本文详细介绍了七种经典的排序算法及其性能分析。每种算法的平均、最坏和最好情况的时间复杂度、辅助空间需求以及稳定性都被列出,帮助读者全面了解这些排序方法的特点。 ... [详细]
  • 本文介绍如何利用动态规划算法解决经典的0-1背包问题。通过具体实例和代码实现,详细解释了在给定容量的背包中选择若干物品以最大化总价值的过程。 ... [详细]
  • 本文详细探讨了Java中的24种设计模式及其应用,并介绍了七大面向对象设计原则。通过创建型、结构型和行为型模式的分类,帮助开发者更好地理解和应用这些模式,提升代码质量和可维护性。 ... [详细]
  • 本文介绍了Java并发库中的阻塞队列(BlockingQueue)及其典型应用场景。通过具体实例,展示了如何利用LinkedBlockingQueue实现线程间高效、安全的数据传递,并结合线程池和原子类优化性能。 ... [详细]
  • 题目描述:给定n个半开区间[a, b),要求使用两个互不重叠的记录器,求最多可以记录多少个区间。解决方案采用贪心算法,通过排序和遍历实现最优解。 ... [详细]
  • 深入理解C++中的KMP算法:高效字符串匹配的利器
    本文详细介绍C++中实现KMP算法的方法,探讨其在字符串匹配问题上的优势。通过对比暴力匹配(BF)算法,展示KMP算法如何利用前缀表优化匹配过程,显著提升效率。 ... [详细]
  • 探讨一个显示数字的故障计算器,它支持两种操作:将当前数字乘以2或减去1。本文将详细介绍如何用最少的操作次数将初始值X转换为目标值Y。 ... [详细]
author-avatar
我心永恒2602922374_902
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有