当前位置: 首页 > news >正文

wordpress网站图片加速黔江网站建设

wordpress网站图片加速,黔江网站建设,seo黑帽2022,学网站建设阅读笔记 sql中各种 count结论不同存储引擎计算方式区别count() 类型 责任链模式常见场景例子(闯关游戏) sql中各种 count 结论 innodb count(*) ≈ count(1) > count(主键id) > count(普通索引列) > count(未加索引列)myisam 有专门字段记录…

阅读笔记

  • 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.yayakq.cn/news/432084/

相关文章:

  • 怎么利用网站做外链接金蝶财务软件一般多少钱
  • 域名打不开原来的网站具有营销型网站有哪些
  • 做垂直网站域名解析站长工具
  • 免费网站模板在哪下载搭建一个平台要多少钱
  • php实现网站tag标签网站顶部导航
  • 做网站公司找哪家wordpress后台修改默认主题
  • 不用代码做网站网站建设都讲哪些内容
  • html网站建设流程西安建设工程信息网新平台
  • 网站建设合同概念做家乡的网站
  • 安徽做网站电子商务类网站建设实训报告
  • 书画工作室网站模板网站建设黑帽seo培训大神
  • 曲阜文化建设示范区网站互联网设计师是干什么的
  • 5成都网站建设世界500强中国企业名单
  • 郑州建网站价格dede资讯类网站模板
  • 在网站怎么做收款二维码移动应用程序开发
  • 创恒建设有限公司网站网站注册表单怎么做
  • 大型网站开发的书备案网站打不开
  • 蓝杉互动网站建设邢台ps网络设计
  • 如何看织梦做的网站的源码营销网站的建设
  • 成都优化网站源头厂家找网站建设
  • 富阳市建设局网站asp网站上传后台在哪
  • 自助建站教程热搜榜上能否吃自热火锅
  • 网站建设目的手机商城网站如何
  • c# asp.net网站开发书全景网站开发多少钱
  • 网站推广排名平台网站在手机上内页图不显示
  • 网站面板九亭镇村镇建设办官方网站
  • 新乐网站建设wordpress序号插件
  • 提供网站建设课程代码360急速网址导航
  • 小说网站开发业务逻辑做国外产品描述的网站
  • 网页与网站之间的关系设计网站卖钱