查询优化过程主要包括哪几个步骤_工艺流程优化

查询优化过程主要包括哪几个步骤_工艺流程优化前情提要 大约在2个月前我开发了一个ip查询接口,当时的需求只需要支持单个IP结果的查询即可,所以在选择上选用了es进行存储,v4和v6单独分索引,结果大概10ms左右就可以返回,需求顺利交付,但是随

前情提要

大约在2个月前我开发了一个ip查询接口,当时的需求只需要支持单个IP结果的查询即可,所以在选择上选用了es进行存储,v4和v6单独分索引,结果大概10ms左右就可以返回,需求顺利交付,但是随着业务的变化与增长,有另外一个同事过来说需要支持一下批量数据的查询,此时就出现了一个问题,另外一个同事的需求是一次查询至多1000个地址,并批量返回,这个情况对于es来说就有一些慢了,在起初接口提供给他的时候,接口经常出现超时,所以就促成了此次优化。

本次优化相关指标:

数据量:700万

查询要求:500ms完成至少1000个ip的结果返回

优化方案

初次尝试

其实初次尝试也没有什么比较好的方案,所以国际惯例,先优化代码。通过分析代码以及日志发现了几个问题:

1.日志中有非ip格式的数据传入,未做合法性校验导致pannic。

2.ip转换的时候会经过一个计算的过程,而这个过程是可以进行批量处理的。

3.索引过多(第一个版本分了3个索引),需要多次查询才能得到准确结果,这会多次去访问es增加了耗时。

第一个版本的伪代码如下:

// 1.接收IP数据
ipList := c.getParams("ipList")  
// 2.传入转换
for ip in ipList {
  transIp(ip)
}
// 3.1 查询第一个索引 找到对应的IpIndex
ipIndex := es.find(transIp)
// 3.2 查询第二个索引 通过ipIndex找到CityIndex
cityIndex := es.find(ipIndex)
// 3.3 查询第三个索引 通过cityIndex找到对应的城市
city := es.find(cityIndex)

通过统计三步查询成为耗时大户,占据大概100ms左右,此时若是单个Ip查询还凑合,如果是1000个一定会炸。

故第一步便是先修复代码里的逻辑错误:

1.增加合法性校验,避免第三方服务传入一些奇怪的字符导致服务pannic。

2.批量处理合成逻辑避免串行耗时。

3.合并索引,将取消IpIndex和CityIndex索引,将第一和第三个索引合并为一个,减少查询次数。

优化过后流程如下: image.png 第一阶段的优化方案

此时已经基本解决了查询耗时的问题,为什么说基本呢,因为借助缓存,我们在第一次请求超时过后,线程仍然会继续执行下去,执行完成后会写入Redis,下一次再进行查询的时候,也就不会访问DB了,那么也就不会超时了,当时由于没有好的思路,所以暂时使用了这一比较挫的方案替代。

几天过后……

再次尝试

距离上次修改大概3周左右,在和前部门的一个组长聊到这个事情,他的第一反应就是数据库选型出了问题,此时为才恍然大悟,于是修改了之前的计划,决定替换掉Elastic Search使用MySQL来进行使用。

使用MySQL来进行优化

有了之前的经验,我迅速组织好了表结构(这里的结构是做过一次合并之后的索引的结构)大概结构如下:

TableName ip_db

id

IpIndex // 此处就是之前提到的IpIndex用于查询Index

IpMessage

……

这里为什么要单独强调IpIndex呢,因为这和我们的查询业务有关,Ip查询是通过IpIndex来找到对应的地址,那么这也告诉我们需要在IpIndex这个字段上添加索引了。接下来我们需要做的就是选择合适的索引进行添加。

索引选择

在选择索引之前,我先贴上这次查询的SQL

select * from ip_db where ipIndex <= xxxx order by ipIndex desc limit 1;

普通索引:普通索引可能会重复,查找到满足条件的第一个记录后,继续查找下个记录,直到碰到第一个不满足记录就返回。

唯一索引:不可重复,和主键一样,查到第一个满足条件的,就停止搜索。

二者性能差距忽略不计,但是我们的IpIndex是不可以重复的,所以我们必须选择唯一索引。

接下来就是选择数据结构,可供选择的数据结构有Hash和btree。

Hash索引一般用于精准查找性能极高(o(1)),无法支持范围查询。

Btree索引B-tree索引更适合进行范围查询,用于查询中的order by 操作。

综上看来,我们两种索引都可以选择,但是Btree,因为Btree支持范围查询,而我们的SQL也更多的是范围查询,其中的=意义不大,直接ipIndex相等的概率很小。

当然mysql的InnoDB中存在一种优化机制,我们称之为自适应Hash索引,当InnoDB注意到某些索引值被使用得非常频繁时,它会在内存中基于B-Tree索引之上再创建一个哈希索引,这样就让B-Tree索引也具有哈希索引的一些优点,比如快速的哈希查找。但这是一个完全自动的、内部的行为,用于无法控制,但用户可以选择完全关闭该动能。

最后的配置
create unique index ip_search_index
    on ip_data.ip_db (ipIndex desc);

当然上述优化,我们同是结合数据库连接池,就完成了本次优化。

最后

经过优化之后,700w的数据访问单个ip查询在10μs左右,综合1000个ip查询耗时在100ms以内,优化前为5s-6s波动。总的来说本次优化所使用的技术不难,重要的事思考的过程,一步一步完成从单个ip10ms查询到单个ip10μs,同时能够承载1000个ip同时查询大大优化了用户体验,通过强化了容错性。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
转载请注明出处: https://daima100.com/13815.html

(0)

相关推荐

  • 通过wireshark抓包来学习TCP HTTP网络协议[亲测有效]

    通过wireshark抓包来学习TCP HTTP网络协议[亲测有效]很多招聘需求上都会要求熟悉TCP/IP协议、socket编程之类的,可见这一块是对于web编程是非常重要的。作为一个野生程序员对这块没什么概念,于是便找来一些书籍想来补补。

    2023-08-09
    115
  • 北京哪里有开住宿费发票

    北京哪里有开住宿费发票电薇13530507261 保-真,可-先-幵-验,陈经理。链接与装载是一个比较晦涩的话题,大家往往容易陷入复杂的细节中而难以看清问题的本来面目。从本质上讲各个系统的编译、链接、装载过程都是大同小异…

    2023-02-16
    138
  • 使用Python绘制曲线图

    使用Python绘制曲线图随着数据时代的到来,数据可视化成为了越来越重要的一个研究领域。在数据分析过程中,图形的作用是非常重要的,它可以帮助我们更好地理解和分析数据。其中,曲线图作为一种常用的数据可视化手段,在科研、商业和工业等领域都有广泛的应用。

    2024-05-01
    67
  • 数据库 简答题_数据库试题

    数据库 简答题_数据库试题
    第一章 数据库概述 1.简述数据管理技术发展的三个阶段以及各个阶段的特点 数据库管理技术发展经过了人工管理阶段,文件系统阶段,数据库系统阶段。 (1)人工管…

    2023-04-04
    154
  • nba2k11最新名单补丁(NBA2k14补丁)

    nba2k11最新名单补丁(NBA2k14补丁)

    2023-08-28
    130
  • ORACLE如何查看当前账号的相关信息总结

    ORACLE如何查看当前账号的相关信息总结关于Oracle数据库的账号,我们在维护数据库的时候,偶尔可能需要获取一些特殊信息。例如,账号的创建时间、账号的状态、账号的锁定时间…..。正常情况下,我们可以通过DBA_USERS获取大部分相关

    2023-04-17
    149
  • sqlserver视图和存储过程_SQL视图存储过程

    sqlserver视图和存储过程_SQL视图存储过程SQL基础随记2 视图 存储过程 View CREATE/ALTER/DROP VIEW ViewName as SELECT(…) 可以在视图的基础上继续创建视图,即,将之前创建的视图当做表名放

    2023-03-16
    153
  • Python Finding List: 搜索引擎优化数据分析利器

    Python Finding List: 搜索引擎优化数据分析利器随着互联网的不断发展,搜索引擎已成为人们获取信息的重要手段。SEO(Search Engine Optimization)优化技术的使用已经成为企业和网站必不可少的一部分。但是如何分析和优化SEO数据呢?Python Finding List是一款强大的Python工具,可以帮助用户从不同的角度进行SEO数据分析和优化。

    2024-01-02
    107

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注