加入收藏 | 设为首页 | 会员中心 | 我要投稿 开发网_开封站长网 (http://www.0378zz.com/)- 科技、AI行业应用、媒体智能、低代码、办公协同!
当前位置: 首页 > 云计算 > 正文

这几种方法,能有效帮你提升接口查询速度

发布时间:2022-07-16 14:12:34 所属栏目:云计算 来源:互联网
导读:1. MySQL查询慢是什么体验? 大多数互联网应用场景都是读多写少,业务逻辑更多分布在写上。对读的要求大概就是要快。那么都有什么原因会导致我们完成一次出色的慢查询呢? 1.1 索引 在数据量不是很大时,大多慢查询可以用索引解决,大多慢查询也因为索引不合
  1. MySQL查询慢是什么体验?
  大多数互联网应用场景都是读多写少,业务逻辑更多分布在写上。对读的要求大概就是要快。那么都有什么原因会导致我们完成一次出色的慢查询呢?
 
  1.1 索引
  在数据量不是很大时,大多慢查询可以用索引解决,大多慢查询也因为索引不合理而产生。
 
  MySQL 索引基于 B+ 树,这句话相信面试都背烂了,接着就可以问最左前缀索引、 B+ 树和各种树了。
 
  1.1.1 什么原因导致索引失效
  建了索引还慢,多半是索引失效(未使用),可用 explain 分析。索引失效常见原因有 :
 
  where 中使用 != 或 <> 或 or 或表达式或函数(左侧)
  like 语句 % 开头
  字符串未加’’
  索引字段区分度过低,如性别
  未匹配最左前缀
  (一张嘴就知道老面试题了) 为什么这些做法会导致失效,成熟的 MySQL 也有自己的想法。
 
  1.1.2 这些原因为什么导致索引失效
  如果要 MySQL 给一个理由,还是那棵 B+ 树。
 
  函数操作
 
  当在 查询 where = 左侧使用表达式或函数时,如字段 A 为字符串型且有索引, 有 where length(a) = 6查询,这时传递一个 6 到 A 的索引树,不难想象在树的第一层就迷路了。
 
  隐式转换
 
  隐式类型转换和隐式字符编码转换也会导致这个问题。
 
  隐式类型转换对于 JOOQ 这种框架来说一般倒不会出现。
  隐式字符编码转换在连表查询时倒可能出现,即连表字段的类型相同但字符编码不同。
  破坏了有序性
 
  至于 Like 语句 % 开头、字符串未加 ’’ 原因基本一致,MySQL 认为对索引字段的操作可能会破坏索引有序性就机智的优化掉了。
 
  不过,对于如性别这种区分度过低的字段,索引失效就不是因为这个原因。
 
  1.1.3 性别字段为什么不要加索引
  为什么索引区分度低的字段不要加索引。盲猜效率低,效率的确低,有时甚至会等于没加。
 
  对于非聚簇索引,是要回表的。假如有 100 条数据,在 sex 字段建立索引,扫描到 51 个 male,需要再回表扫描 51 行。还不如直接来一次全表扫描呢。
 
  所以,InnoDB 引擎对于这种场景就会放弃使用索引,至于区分度多低多少会放弃,大致是某类型的数据占到总的 30% 左右时,就会放弃使用该字段的索引,有兴趣可以试一下。
 
  1.1.4 有什么好用且简单的索引方法
  前面说到大多慢查询都源于索引,怎么建立并用好索引。这里有一些简单的规则。
 
  索引下推:性别字段不适合建索引,但确实存在查询场景怎么办?如果是多条件查询,可以建立联合索引利用该特性优化。
  覆盖索引:也是联合索引,查询需要的信息在索引里已经包含了,就不会再回表了。
  前缀索引:对于字符串,可以只在前 N 位添加索引,避免不必要的开支。假如的确需要如关键字查询,那交给更合适的如 ES 或许更好。
  不要对索引字段做函数操作
  对于确定的、写多读少的表或者频繁更新的字段都应该考虑索引的维护成本。
 
  这种情况常见于建了一大堆索引,查询条件一大堆。没使用你想让它用的那一个,而是选了个区分度低的,导致过多的扫描。造成的原因基本有两个:
 
  信息统计不准确:可以使用 analyze table x重新分析。
  优化器误判:可以 force index强制指定。或修改语句引导优化器,增加或删除索引绕过。
  但根据我浅薄的经验来看,更可能是因为你建了些没必要的索引导致的。不会真有人以为 MySQL 没自己机灵吧?
 
  除了上面这些索引原因外,还有下面这些不常见或者说不好判断的原因存在。
 
  1.2 等MDL锁
  在 MySQL 5.5 版本中引入了 MDL,对一个表做 CRUD 操作时,自动加 MDL 读锁;对表结构做变更时,加 MDL 写锁。读写锁、写锁间互斥。
 
  当某语句拿 MDL 写锁就会阻塞 MDL 读锁,可以使用show processlist命令查看处于Waiting for table metadata lock状态的语句。
 
  1.3 等 flush
  flush 很快,大多是因为 flush 命令被别的语句堵住,它又堵住了 select 。通过show processlist命令查看时会发现处于Waiting for table flush状态。
 
  1.4 等行锁
  某事物持有写锁未提交。
 
  1.5 当前读
  InnoDB 默认级别是可重复读。设想一个场景:事物 A 开始事务,事务 B 也开始执行大量更新。B 率先提交, A 是当前读,就要依次执行 undo log ,直到找到事务 B 开始前的值。
 
  1.6 大表场景
  在未二次开发的 MYSQL 中,上亿的表肯定算大表,这种情况即使在索引、查询层面做到了较好实现,面对频繁聚合操作也可能会出现 IO 或 CPU 瓶颈,即使是单纯查询,效率也会下降。
 
  所以对于大表常见优化即是分库分表和读写分离了。
 
  1.6.1 分库分表
  方案
 
  是分库还是分表呢?这要具体分析。
 
  如果磁盘或网络有 IO 瓶颈,那就要分库和垂直分表。
  如果是 CPU 瓶颈,即查询效率偏低,水平分表。
  水平即切分数据,分散原有数据到更多的库表中。
  垂直即按照业务对库,按字段对表切分。
 
  工具方面有 sharding-sphere、TDDL、Mycat。动起手来需要先评估分库、表数,制定分片规则选 key,再开发和数据迁移,还要考虑扩容问题。
 
  问题
 
  实际运行中,写问题不大,主要问题在于唯一 ID 生成、非 partition key 查询、扩容。
 
  唯一 ID 方法很多,DB 自增、Snowflake、号段、一大波GUID算法等。
  非 partition key 查询常用映射法解决,映射表用到覆盖索引的话还是很快的。或者可以和其他 DB 组合。
  扩容要根据分片时的策略确定,范围分片的话就很简单,而随机取模分片就要迁移数据了。也可以用范围 + 取模的模式分片,先取模再范围,可以避免一定程度的数据迁移。
  当然,如果分库还会面临事务一致性和跨库 join 等问题。
 
  1.6.2 读写分离
  为什么要读写分离
 
  分表针对大表解决 CPU 瓶颈,分库解决 IO 瓶颈,二者将存储压力解决了。但查询还不一定。
 
  如果落到 DB 的 QPS 还是很高,且读远大于写,就可以考虑读写分离,基于主从模式将读的压力分摊,避免单机负载过高,同时也保证了高可用,实现了负载均衡。
 
  问题
 
  主要问题有过期读和分配机制。
 
  过期读,也就是主从延时问题,这个对于。
  分配机制,是走主还是从库。可以直接代码中根据语句类型切换或者使用中间件。
 
  1.7 小结
 
  以上列举了 MySQL 常见慢查询原因和处理方法,介绍了应对较大数据场景的常用方法。
 
  分库分表和读写分离是针对大数据或并发场景的,同时也为了提高系统的稳定和拓展性。但也不是所有的问题都最适合这么解决。
 
  2. 如何评价 ElasticSearch
  前文有提到对于关键字查询可以使用 ES。那接着聊聊 ES 。
 
  2.1 可以干什么
  ES 是基于 Lucene 的近实时分布式搜索引擎。使用场景有全文搜索、NoSQL Json 文档数据库、监控日志、数据采集分析等。
 
  对非数据开发来说,常用的应该就是全文检索和日志了。ES 的使用中,常和 Logstash, Kibana 结合,也成为 ELK 。先来瞧瞧日志怎么用的。
 
  下面是我司日志系统某检索操作:打开 Kibana 在 Discover 页面输入格式如 “xxx” 查询。
 
  该操作可以在 Dev Tools 的控制台替换为:
 
  这几种技巧,能有效帮你提升接口查询速度
 
  2.2 ES 的结构
  在 ES 7.0 之前存储结构是 Index -> Type -> Document,按 MySQL 对比就是 database - table - id(实际这种对比不那么合理)。7.0 之后 Type 被废弃了,就暂把 index 当做 table 吧。
 
  在 Dev Tools 的 Console 可以通过以下命令查看一些基本信息。也可以替换为 crul 命令。

(编辑:开发网_开封站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读