阅读笔记lv.1

阅读笔记

  • sql中各种 count
    • 结论
    • 不同存储引擎计算方式
    • 区别
    • count() 类型
  • 责任链模式
    • 常见场景
    • 例子(闯关游戏)

sql中各种 count

结论

  • innodb
count(*)count(1) > count(主键id) > count(普通索引列) > count(未加索引列)
  • myisam
    有专门字段记录全表的行数,直接读这个字段就好了(innodb则需要一行行去算

  • 如果确实需要获取行数,且可以接受不那么精确的行数(只需要判断大概的量级) 的话,那可以用explain里的rows,这可以满足大部分的监控场景,实现简单

  • 如果要求行数准确 ,可以建个新表,里面专门放表行数的信息

  • 如果对实时性要求比较高 的话,可以将更新行数的sql放入到对应事务里,这样既能满足事务隔离性,还能快速读取到行数信息

  • 如果对实时性要求不高 ,接受一小时或者一天的更新频率,那既可以自己写脚本遍历全表后更新行数信息。也可以将通过监听binlog将数据导入hive,需要数据时直接通过hive计算得出

不同存储引擎计算方式

  • count()方法的目的是计算当前sql语句查询得到的非NULL的行数
    在这里插入图片描述
  • 虽然在server层都叫count()方法,但在不同的存储引擎下,它们的实现方式是有区别的
    • 比如同样是读全表数据
select count(*) from table (where *** )

当数据表小的时候,这是没问题的,但当数据量大的时候,比如未发送的短信到了百万量级 的时候,你就会发现,上面的sql查询时间会变得很长,最后timeout报错,查不出结果了 。

    • 使用 myisam引擎 的数据表里有个记录当前表里有几行数据的字段,直接读这个字段返回就好了,因此速度快得飞起
    • 使用innodb引擎 的数据表,则会选择体积最小的索引树 ,然后通过遍历叶子节点的个数挨个加起来,这样也能得到全表数据

区别

为什么innodb不能像myisam那样实现count()方法

  • 最大的区别在于myisam不支持事务,而innodb支持事务
    而事务,有四层隔离级别,其中默认隔离级别就是可重复读隔离级别(RR)

    • innodb引擎通过MVCC实现了可重复隔离级别 ,事务开启后,多次执行同样的select快照读 ,要能读到同样的数据。
    • 对于两个事务A和B,一开始表假设就2条 数据,那事务A一开始确实是读到2条数据。事务B在这期间插入了1条数据,按道理数据库其实有3条数据了,但由于可重复读的隔离级别,事务A依然还是只能读到2条数据。
    • 因此由于事务隔离级别的存在,不同的事务在同一时间下,看到的表内数据行数是不一致的 ,因此innodb,没办法,也没必要像myisam那样单纯的加个count字段信息在数据表上

count() 类型

count方法的大原则是server层会从innodb存储引擎里读来一行行数据,并且只累计非null的值 。但这个过程,根据count()方法括号内的传参,有略有不同。

  • count(*)
    server层拿到innodb返回的行数据,不对里面的行数据做任何解析和判断 ,默认取出的值肯定都不是null,直接行数+1
  • count(1)
    server层拿到innodb返回的行数据,每行放个1进去,默认不可能为null,直接行数+1.
    • InnoDB 引擎遍历整张表,但不取值。server 层对于返回的每一行,放一个数字“1”进去,判断是不可能为空的,按行累加
  • count(字段)
    count(字段)是不统计,字段值为null的值
    • count(主键 id) 来说,InnoDB 引擎会遍历整张表,把每一行的 id 值都取出来,返回给 server 层。server 层拿到 id 后,判断是不可能为空的,就按行累加
    • count(字段),server要字段,就返回字段,如果字段为空,就不做统计,字段的值过大,都会造成效率低下

      由于指明了要count某个字段,innodb在取数据的时候,会把这个字段解析出来 返回给server层,所以会比count(1)和count(*)多了个解析字段出来的流程

在这里插入图片描述

责任链模式

  • 责任链模式是一种行为设计模式, 允许你将请求沿着处理者链进行发送。收到请求后, 每个处理者均可对请求进行处理, 或将其传递给链上的下个处理者。

在这里插入图片描述

常见场景

  1. 多条件的流程判断(如导入文件校验条件较多,且需逐层校验成功的;或类似闯关游戏,必须达到一定分数/条件才能开始下一关)
    导入功能可能【模板方法】更适合
    • 模板方法可以提供大部分相同的【模板】,根据不同的导入场景做小部分调整,实现各自独立的业务,大体上导入功能差不多
    • 一次性实现一个算法的不变部分,并将可变的行为留给子类来实现
    • 各子类中公共的行为被提取出来并集中到一个公共父类中,从而避免代码重复
      在这里插入图片描述
  1. ERP 系统流程审批:总经理、人事经理、项目经理
  2. Java 过滤器的底层实现 Filter

例子(闯关游戏)

  • 假设现在有一个闯关游戏,进入下一关的条件是上一关的分数要高于 xx:

  • 游戏一共 3 个关卡
    进入第二关需要第一关的游戏得分大于等于 80
    进入第三关需要第二关的游戏得分大于等于 90

简易版(多层 if 逐层判断是否满足条件)

//第一关
public class FirstPassHandler {public int handler(){System.out.println("第一关-->FirstPassHandler");return 80;}
}//第二关
public class SecondPassHandler {public int handler(){System.out.println("第二关-->SecondPassHandler");return 90;}
}//第三关
public class ThirdPassHandler {public int handler(){System.out.println("第三关-->ThirdPassHandler,这是最后一关啦");return 95;}
}//客户端
public class HandlerClient {public static void main(String[] args) {FirstPassHandler firstPassHandler = new FirstPassHandler();//第一关SecondPassHandler secondPassHandler = new SecondPassHandler();//第二关ThirdPassHandler thirdPassHandler = new ThirdPassHandler();//第三关int firstScore = firstPassHandler.handler();//第一关的分数大于等于80则进入第二关if(firstScore >= 80){int secondScore = secondPassHandler.handler();//第二关的分数大于等于90则进入第二关if(secondScore >= 90){thirdPassHandler.handler();}}}
}
  • 实际上的 handle() 根据业务来传参及计算分数
  • 缺点
    当关数越多/条件越多时代码会变得很长,无限月读(if 嵌套)
if(1关通过){// 第2关 游戏if(2关通过){// 第3关 游戏if(3关通过){// 第4关 游戏if(4关通过){// 第5关 游戏if(5关通过){// 第6关 游戏if(6关通过){//...}}} }}
}

升级(责任链链表拼接每一关)

  • 可以通过链表将每一关连接起来,形成责任链的方式,第一关通过后是第二关,第二关通过后是第三关… (减少客户端代码过多的 if 嵌套)
public class FirstPassHandler {/*** 第一关的下一关是 第二关*/private SecondPassHandler secondPassHandler;public void setSecondPassHandler(SecondPassHandler secondPassHandler) {this.secondPassHandler = secondPassHandler;}//本关卡游戏得分private int play(){return 80;}public int handler(){System.out.println("第一关-->FirstPassHandler");if(play() >= 80){//分数>=80 并且存在下一关才进入下一关if(this.secondPassHandler != null){return this.secondPassHandler.handler();}}return 80;}
}public class SecondPassHandler {/*** 第二关的下一关是 第三关*/private ThirdPassHandler thirdPassHandler;public void setThirdPassHandler(ThirdPassHandler thirdPassHandler) {this.thirdPassHandler = thirdPassHandler;}//本关卡游戏得分private int play(){return 90;}public int handler(){System.out.println("第二关-->SecondPassHandler");if(play() >= 90){//分数>=90 并且存在下一关才进入下一关if(this.thirdPassHandler != null){return this.thirdPassHandler.handler();}}return 90;}
}public class ThirdPassHandler {//本关卡游戏得分private int play(){return 95;}/*** 这是最后一关,因此没有下一关*/public int handler(){System.out.println("第三关-->ThirdPassHandler,这是最后一关啦");return play();}
}public class HandlerClient {public static void main(String[] args) {FirstPassHandler firstPassHandler = new FirstPassHandler();//第一关SecondPassHandler secondPassHandler = new SecondPassHandler();//第二关ThirdPassHandler thirdPassHandler = new ThirdPassHandler();//第三关firstPassHandler.setSecondPassHandler(secondPassHandler);//第一关的下一关是第二关secondPassHandler.setThirdPassHandler(thirdPassHandler);//第二关的下一关是第三关//说明:因为第三关是最后一关,因此没有下一关//开始调用第一关 每一个关卡是否进入下一关卡 在每个关卡中判断firstPassHandler.handler();}
}
  • 缺点
    从代码中可以看到,每一关的处理逻辑中都有一个 set**PassHandler() 方法,只是参数类型不一样,但是作用其实是一样的,只是用来判断是否有下一关
    每个关卡中都有下一关的成员变量并且是不一样的,形成链很不方便,代码扩展性不行

进化(责任链改造—抽象)

  • 每个关卡中都有下一关的成员变量并且是不一样的,那么我们可以在关卡上抽象出一个父类或者接口,然后每个具体的关卡去继承或者实现,将参数合并成一个,不再需要在各自的 set**PassHandler 中传递不同的参数
  • 责任链设计模式的基本组成
    • 抽象处理者(Handler)角色: 定义一个处理请求的接口,包含抽象处理方法和一个后继连接
    • 具体处理者(Concrete Handler)角色: 实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理请求则处理,否则将该请求转给它的后继者
    • 客户类(Client)角色: 创建处理链,并向链头的具体处理者对象提交请求,它不关心处理细节和请求的传递过程
      在这里插入图片描述
public abstract class AbstractHandler {/*** 下一关用当前抽象类来接收*/protected AbstractHandler next;public void setNext(AbstractHandler next) {this.next = next;}public abstract int handler();
}public class FirstPassHandler extends AbstractHandler{private int play(){return 80;}@Overridepublic int handler(){System.out.println("第一关-->FirstPassHandler");int score = play();if(score >= 80){//分数>=80 并且存在下一关才进入下一关if(this.next != null){return this.next.handler();}}return score;}
}public class SecondPassHandler extends AbstractHandler{private int play(){return 90;}public int handler(){System.out.println("第二关-->SecondPassHandler");int score = play();if(score >= 90){//分数>=90 并且存在下一关才进入下一关if(this.next != null){return this.next.handler();}}return score;}
}public class ThirdPassHandler extends AbstractHandler{private int play(){return 95;}public int handler(){System.out.println("第三关-->ThirdPassHandler");int score = play();if(score >= 95){//分数>=95 并且存在下一关才进入下一关if(this.next != null){return this.next.handler();}}return score;}
}public class HandlerClient {public static void main(String[] args) {FirstPassHandler firstPassHandler = new FirstPassHandler();//第一关SecondPassHandler secondPassHandler = new SecondPassHandler();//第二关ThirdPassHandler thirdPassHandler = new ThirdPassHandler();//第三关// 和上面没有更改的客户端代码相比,只有这里的set方法发生变化,其他都是一样的firstPassHandler.setNext(secondPassHandler);//第一关的下一关是第二关secondPassHandler.setNext(thirdPassHandler);//第二关的下一关是第三关//说明:因为第三关是最后一关,因此没有下一关//从第一个关卡开始firstPassHandler.handler();}
}
  • 从代码中可以看到,此次进化引入了一个 抽象处理者,让每一关的具体处理者都继承该类,后续在设置下一关对象的时候就不必各自编写各自的set**PassHandler() 方法,而是直接使用相同的处理方法,只需要编写各自的 handler() 得分方法,进一步简化了代码

终极进化(责任链工厂改造)

public enum GatewayEnum {// handlerId, 拦截者名称,全限定类名,preHandlerId,nextHandlerIdAPI_HANDLER(new GatewayEntity(1, "api接口限流", "cn.dgut.design.chain_of_responsibility.GateWay.impl.ApiLimitGatewayHandler", null, 2)),BLACKLIST_HANDLER(new GatewayEntity(2, "黑名单拦截", "cn.dgut.design.chain_of_responsibility.GateWay.impl.BlacklistGatewayHandler", 1, 3)),SESSION_HANDLER(new GatewayEntity(3, "用户会话拦截", "cn.dgut.design.chain_of_responsibility.GateWay.impl.SessionGatewayHandler", 2, null)),;GatewayEntity gatewayEntity;public GatewayEntity getGatewayEntity() {return gatewayEntity;}GatewayEnum(GatewayEntity gatewayEntity) {this.gatewayEntity = gatewayEntity;}
}public class GatewayEntity {private String name;private String conference;private Integer handlerId;private Integer preHandlerId;private Integer nextHandlerId;
}public interface GatewayDao {/*** 根据 handlerId 获取配置项* @param handlerId* @return*/GatewayEntity getGatewayEntity(Integer handlerId);/*** 获取第一个处理者* @return*/GatewayEntity getFirstGatewayEntity();
}public class GatewayImpl implements GatewayDao {/*** 初始化,将枚举中配置的handler初始化到map中,方便获取*/private static Map<Integer, GatewayEntity> gatewayEntityMap = new HashMap<>();static {GatewayEnum[] values = GatewayEnum.values();for (GatewayEnum value : values) {GatewayEntity gatewayEntity = value.getGatewayEntity();gatewayEntityMap.put(gatewayEntity.getHandlerId(), gatewayEntity);}}@Overridepublic GatewayEntity getGatewayEntity(Integer handlerId) {return gatewayEntityMap.get(handlerId);}@Overridepublic GatewayEntity getFirstGatewayEntity() {for (Map.Entry<Integer, GatewayEntity> entry : gatewayEntityMap.entrySet()) {GatewayEntity value = entry.getValue();//  没有上一个handler的就是第一个if (value.getPreHandlerId() == null) {return value;}}return null;}
}public class GatewayHandlerEnumFactory {private static GatewayDao gatewayDao = new GatewayImpl();// 提供静态方法,获取第一个handlerpublic static GatewayHandler getFirstGatewayHandler() {GatewayEntity firstGatewayEntity = gatewayDao.getFirstGatewayEntity();GatewayHandler firstGatewayHandler = newGatewayHandler(firstGatewayEntity);if (firstGatewayHandler == null) {return null;}GatewayEntity tempGatewayEntity = firstGatewayEntity;Integer nextHandlerId = null;GatewayHandler tempGatewayHandler = firstGatewayHandler;// 迭代遍历所有handler,以及将它们链接起来while ((nextHandlerId = tempGatewayEntity.getNextHandlerId()) != null) {GatewayEntity gatewayEntity = gatewayDao.getGatewayEntity(nextHandlerId);GatewayHandler gatewayHandler = newGatewayHandler(gatewayEntity);tempGatewayHandler.setNext(gatewayHandler);tempGatewayHandler = gatewayHandler;tempGatewayEntity = gatewayEntity;}// 返回第一个handlerreturn firstGatewayHandler;}/*** 反射实体化具体的处理者* @param firstGatewayEntity* @return*/private static GatewayHandler newGatewayHandler(GatewayEntity firstGatewayEntity) {// 获取全限定类名String className = firstGatewayEntity.getConference(); try {// 根据全限定类名,加载并初始化该类,即会初始化该类的静态段Class<?> clazz = Class.forName(className);return (GatewayHandler) clazz.newInstance();} catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) {e.printStackTrace();}return null;}}public class GetewayClient {public static void main(String[] args) {GetewayHandler firstGetewayHandler = GetewayHandlerEnumFactory.getFirstGetewayHandler();firstGetewayHandler.service();}
}
  • 待深究

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/619807.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计算机体系结构----缓存一致性/多处理机

本文严禁转载&#xff0c;仅供学习使用。参考资料来自中国科学院大学计算机体系结构课程PPT以及《Digital Design and Computer Architecture》、《超标量处理器设计》、同济大学张晨曦教授资料。如有侵权&#xff0c;联系本人修改。 本文衔接上文计算机体系结构----存储系统 …

python爬虫,验证码识别,携带cookies请求

古诗词网案例!!! 识别验证码类型: # 此处用到的图片验证码识别网址为:http://ttshitu.com/ 图鉴 import base64 import json import requests # 一、图片文字类型(默认 3 数英混合): # 1 : 纯数字 # 1001:纯数字2 # 2 : 纯英文 # 1002:纯英文2 # 3 : 数英混合 # 1003:…

用通俗易懂的方式讲解:大模型微调方法总结

大家好&#xff0c;今天给大家分享大模型微调方法&#xff1a;LoRA,Adapter,Prefix-tuning&#xff0c;P-tuning&#xff0c;Prompt-tuning。 文末有大模型一系列文章及技术交流方式&#xff0c;传统美德不要忘了&#xff0c;喜欢本文记得收藏、关注、点赞。 文章目录 1、LoRA…

轻松查看WiFi密码的神奇脚本,让你忘记密码也不再是问题

说在前面 &#x1f388;本文介绍了一个便捷的脚本&#xff0c;可以帮助你获取电脑中保存的所有Wi-Fi网络的密码。不再需要担心忘记Wi-Fi密码或手动查找密码的麻烦&#xff0c;只需运行脚本即可一键获取。 一、引言 互联网的普及让我们离不开Wi-Fi网络&#xff0c;但忘记密码时…

怎么安装es、kibana(单点安装)

1.部署单点es 1.1.创建网络 因为我们还需要部署kibana容器&#xff0c;因此需要让es和kibana容器互联。这里先创建一个网络&#xff1a; docker network create es-net1.2.加载镜像 这里我们采用elasticsearch的7.12.1版本的镜像&#xff0c;这个镜像体积非常大&#xff0c…

用C语言采集亚马逊amazon产品数据

上一篇文章我是用C写的一个爬取亚马逊的爬虫程序&#xff0c;相信大家已经看过了&#xff0c;这次呢&#xff0c;我依然使用C语言来写一个爬虫&#xff0c;大体上思路是和之前一样&#xff0c;只是支持的库以及语法有些区别&#xff0c;具体的呢我会一一解释出来&#xff0c;方…

android自定义来电秀UI

简单来电秀功能&#xff0c;效果如图&#xff1a; 底部附上demo 一、新建一个PhoneCallService服务&#xff0c;在服务中监听来电等状态&#xff0c;且控制UI显示 public class PhoneCallService extends InCallService {private final Call.Callback callback new Call.Ca…

仿真机器人-深度学习CV和激光雷达感知(项目2)day01

文章目录 前言项目介绍功能与技术简介硬件要求环境配置虚拟机运行项目demo 前言 &#x1f4ab;你好&#xff0c;我是辰chen&#xff0c;本文旨在准备考研复试或就业 &#x1f4ab;本文内容是我为复试准备的第二个项目 &#x1f4ab;欢迎大家的关注&#xff0c;我的博客主要关注…

如何给AI下达精准的指令,哪些提示词对于AI是有效的?

刚上手那会&#xff0c;我倾向于将 prompt 翻译为“指令”&#xff0c;但这并不精确。“指令”通常对应instructions&#xff0c;属于 prompt 中的纯指令部分&#xff0c;通常是一个动宾结构&#xff08;做什么&#xff09;。剩下的部分更多是描述&#xff08;describe&#xf…

stable-diffusion 学习笔记

从效果看Stable Diffusion中的采样方法 参考&#xff1a;Ai 绘图日常 篇二&#xff1a;从效果看Stable Diffusion中的采样方法_软件应用_什么值得买 大概示例&#xff1a;

Linux:信号

目录 1.信号 2.信号的过程 a.信号的产生 1:键盘产生, 异常产生 2:系统调用产生信号 3.软件条件产生信号 4.硬件异常产生信号 b.信号的发送 c.信号的处理 d.总结与思考 3.信号保存 1.信号及其它相关常见概念 2.在内核中的表示 3.sigset_t 4. 信号集操作函数 4.信…

Arduino开发实例-AS608光学指纹传感器驱动

AS608光学指纹传感器驱动 文章目录 AS608光学指纹传感器驱动1、AS608光学指纹传感器介绍2、硬件准备及接线3、代码实现3.1 指纹录入3.2 指纹匹配验证1、AS608光学指纹传感器介绍 AS608 光学指纹传感器可用于扫描指纹,它也可以通过串行通信将处理后的数据发送到微控制器。 所有…

gem5学习(12):理解gem5 统计信息和输出——Understanding gem5 statistics and output

目录 一、config.ini 二、config.json 三、stats.txt 官方教程&#xff1a;gem5: Understanding gem5 statistics and output 在运行 gem5 之后&#xff0c;除了仿真脚本打印的仿真信息外&#xff0c;还会在根目录中名为 m5out 的目录中生成三个文件&#xff1a; config.i…

【QT】QMessageBox 弹出消息框,对话确认框(确定/取消)

1.无互动 QMessageBox::information(nullptr,"信息","登陆成功");2.互动&#xff1a;确定、取消 QMessageBox::StandardButton box; box QMessageBox::question(this, "提示", "确定要添加吗?", QMessageBox::Yes|QMessageBox::…

RAG代码实操之斗气强者萧炎

&#x1f4d1;前言 本文主要是【RAG】——RAG代码实操的文章&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是听风与他&#x1f947; ☁️博客首页&#xff1a;CSDN主页听风与他 &#x1f304;每日一句&#x…

Netty 介绍、使用场景及案例

Netty 介绍、使用场景及案例 1、Netty 介绍 https://github.com/netty/netty Netty是一个高性能、异步事件驱动的网络应用程序框架&#xff0c;用于快速开发可扩展的网络服务器和客户端。它是一个开源项目&#xff0c;最初由JBoss公司开发&#xff0c;现在由社区维护。Netty的…

企业网络出口部署案例

知识改变命运&#xff0c;技术就是要分享&#xff0c;有问题随时联系&#xff0c;免费答疑&#xff0c;欢迎联系&#xff01; 厦门微思网络​​​​​​ https://www.xmws.cn 华为认证\华为HCIA-Datacom\华为HCIP-Datacom\华为HCIE-Datacom Linux\RHCE\RHCE 9.0\RHCA\ Oracle O…

myql进阶-一条查询sql在mysql的执行过程

目录 1. 流程图 2. 各个过程 2.1 连接器 2.2 分析器 2.3 优化器 2.4 执行器 2.5 注意点 1. 流程图 2. 各个过程 假设我们执行一条sql语句如下&#xff1a; select * from t_good where good_id 1 2.1 连接器 首先我们会和mysql建立连接&#xff0c;此时就会执行到连接…

C++20结构化绑定应用实例(二百五十六)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

猫头虎分享:探索TypeScript的世界 — TS基础入门 ‍

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通Golang》…