您当前的位置:首页 > 电脑百科 > 数据库 > 百科

性能优化技巧 - 查找

时间:2021-03-03 10:37:05  来源:  作者:

【摘要】

日常生活中,我们会遇到各种各样的数据,小到公司通讯录,大到互联网用户行为分析。在进行数据分析处理的过程中,查询是必不可少的环节,如何更加高效地进行数据查询。点击:性能优化技巧 - 查询,来乾学院一探究竟!

SPL为用户提供了强大的索引机制以及针对不同场景中各对象的查询函数,善加运用,可以显著提高查询性能。

1 键值查找

1.1 序表

我们先建立一个份“通话记录”的模拟数据,通过这份数据,来比较一下不同查询函数对序表查询性能的影响。建立模拟数据的代码如下:

性能优化技巧 - 查找

 

代码1.1.1

其中部分数据如下:

性能优化技巧 - 查找

 

图1.1.1

对序表进行查询,通常我们会想到使用A.select()函数。我们来看一下使用该函数的效果:

性能优化技巧 - 查找

 

代码1.1.2

查询耗时为80毫秒。

对序表的键值进行查询时,可以利用A.find()函数进行查询。示例代码如下:

性能优化技巧 - 查找

 

代码1.1.3

查询耗时为1毫秒。

这是因为在集算器的序表中,可以指定某个或某些字段作为主键,基于主键的查找可以使用专门的函数。比如代码1.1.3中A5的find函数,不仅能简化书写,更能有效地提高计算性能。

当键值较多时,我们使用函数A.find@k ()进行批量键值查找。示例代码如下:

性能优化技巧 - 查找

 

代码1.1.4

要注意的是,在使用A.find()函数时,需事先建立主键,否则会报“缺少主键”的错误。

利用主键值查找的函数,可以有效地提升计算性能,是由于在序表中为主键建立索引表。在代码1.1.4中,未建立索引时,平均查询时间在1400毫秒左右;建立索引后,查询平均耗时不到1毫秒。

序表中的数据量越大,需要查找的次数越多,对效率的提升就越明显。

当查询条件对应多个键时,示例代码如下:

性能优化技巧 - 查找

 

代码1.1.5

switch/join函数同样需要根据主键值在序表中查找记录,使用时会对维表自动建立索引。若在多线程fork函数之前没有对相应维表建立索引,就会在每个线程中都自动为该维表建立一个索引,执行过程中会消耗更多内存,这样有可能会造成内存溢出,如图1.1.1.2,要注意避免,较好的处理方式可以参考图 1.1.3。

性能优化技巧 - 查找

 

图 1.1.2 fork中的每个线程都自动建立了索引导致内存溢出

性能优化技巧 - 查找

 

图 1.1.3 fork执行前,先对维表建立索引

1.2 集文件

对有序的集文件进行查找,可以使用f.iselect()函数实现二分查找,该函数也支持批量查找,下面是个基于集文件使用f.iselect()批量查找的例子:

性能优化技巧 - 查找

 

代码1.2.1

代码1.2.1,建立集文件voiceBill@z.btx。显然,Subscriber是有序的。

性能优化技巧 - 查找

 

代码1.2.2

代码1.2.2,因为f.iselect()是个二分查找函数,所以需要注意代码中的A2作为查询序列,与集文件的编号一样,都需要有序。还要注意,这里的选项@b不是二分法的意思,而是读取通过f.export()函数导出的集文件。该集文件导出时,注意需要使用选项@z,否则在使用f.iselect ()对集文件进行查询时会报错。

假设数据总量为N,使用二分法进行查找的时间复杂度为logN(以 2 为底),当数据量越大,性能提升也就越明显。

1.3 组表

组表也有类似序表的T.find()和T.find@k()函数,可以高效地实现键值查找。适合于在大维表中找出少量记录的场景。我们来看这样一个例子:

性能优化技巧 - 查找

 

代码1.3.1

代码1.3.1,建立组表文件voiceBill.ctx,其中Subscriber是该组表的维。

性能优化技巧 - 查找

 

代码1.3.2

代码1.3.2,对组表使用cs.select()函数进行查询,耗时为:13855毫秒。

性能优化技巧 - 查找

 

代码1.3.3

代码1.3.3,对组表使用T.find()函数进行查询,耗时为:77毫秒。

对比可见:对于有维的组表,可以使用类似序表的T.find()函数,进行单个或者批量键值的查询,其查询效率远高于从筛选后的游标中取数。

2 索引查找

组表上可以建立三种索引,每种索引针对的情况也不同,分别为:

1、 hash索引,适合单值查找,比如枚举类型;

2、 排序索引,适合区间查找,比如数字、日期、时间类型;

3、 全文索引,用于模糊查询,比如字符串类型。

下面我们来建立一个组表,使其数据类型覆盖以上三种索引,如下:

性能优化技巧 - 查找

 

代码2.1

代码2.1建立的组表,前十条记录如下:

性能优化技巧 - 查找

 

图2.1

性能优化技巧 - 查找

 

代码2.2

代码2.2,根据每列数据类型的特点,建立不同类型的索引。建立好的索引和组表文件如图2.2:

性能优化技巧 - 查找

 

图2.2

集算器能自动识别条件找到合适的索引,等值和区间都可以,like(“A*”)式的也支持。我们来看下效果:

等值查找

性能优化技巧 - 查找

 

代码2.3

性能优化技巧 - 查找

 

代码2.4

代码2.3是没有省略索引名称的写法,代码2.4是省略索引名称的写法。两者时间消耗基本相同,都是100毫秒左右。

性能优化技巧 - 查找

 

代码2.5

代码2.5使用普通游标查询同样的记录,查询耗时则需要40秒左右。

区间查找

性能优化技巧 - 查找

 

代码2.6

代码2.6对Subscriber使用排序索引,进行区间查找,查询耗时是70毫秒左右。

性能优化技巧 - 查找

 

代码2.7

代码2.7使用普通游标查询同样条件的记录,查询耗时则需要40秒左右。

模糊查找

性能优化技巧 - 查找

 

代码2.8

代码2.8对Company使用全文索引,进行模糊查询,查询耗时是1500毫秒左右。

性能优化技巧 - 查找

 

代码2.9

代码2.9使用普通游标查询同样条件的记录,查询耗时则需要40秒左右。

当数据规模更大时,例如:

性能优化技巧 - 查找

 

代码2.10

代码2.10,建造了10亿条结构如图2.3的组表文件employee.ctx。

性能优化技巧 - 查找

 

图2.3

性能优化技巧 - 查找

 

代码2.11

代码2.11中,对大部分列建立了索引。组表与索引的各个文件如图2.4。

性能优化技巧 - 查找

 

图2.4

多等值条件项&&时,可以分别为每个字段建立索引。集算器能够快速在多个索引中用归并算法计算交集。比如:

性能优化技巧 - 查找

 

代码2.12

代码2.12,查询条件均为等值查询,A3查出记录数为324条,耗时31883毫秒。

但区间条件时不能再用归并计算交集,集算器将只对其中一个条件使用索引,另一个条件使用遍历计算,效果就会差,比如:

性能优化技巧 - 查找

 

代码2.13

代码2.13,查询条件均为区间条件,A3查出记录数为389条,耗时70283毫秒。

3 索引缓存

组表索引提供了两级缓存机制,可以用index@2或者index@3预先把索引的索引读入内存,如果需要重复多次使用索引查找,则可以有效提高性能。

选项@2、@3的意思分别是将索引的第二、三级缓存先加载进内存。经过索引缓存的预处理,第一遍查询时间也能达到查询数百次后才能达到的极限值。@2相比@3缓存的内容少,效果相对差一点,但内存占用也更少。使用时需要程序员根据具体场景来权衡@2还是@3。

性能优化技巧 - 查找

 

代码3.1

代码3.1,基于代码2.10建造的组表文件,不使用索引缓存,查询耗时为31883毫秒。

性能优化技巧 - 查找

 

代码3.2

代码3.2使用第三级索引缓存,查询耗时为5225毫秒。

这里使用的是列存组表,列存采用了数据分块并压缩的算法,对于遍历运算来讲,访问数据量会变小,也就会具有更好的性能。但对于基于索引随机取数的场景,由于要有额外的解压过程,而且每次取数都会针对整个分块,运算复杂度会高很多。因此,从原理上分析,这时候的性能应当会比行存要差。将组表转为行存后,查询耗时仅为1592毫秒。

索引缓存在并行时可以复用,如下:

性能优化技巧 - 查找

 

代码3.3

代码3.3,并行时,A5的每个线程中都可以使用A2、A3中建立的第三级索引缓存,最终查询耗时为21376毫秒。

4 带值索引

组表的行存和列存形式都支持索引,列存索引查找比行存性能差,返回结果集较少时差异不明显,大量返回时会有明显劣势,在设计存储方案时要权衡。

性能优化技巧 - 查找

 

代码4.1

代码4.1建立组表文件id_600m.ctx,结构为(#id,data) ,包含6亿条记录,其中:

A1:包含 26 个英文字母和 10 个阿拉伯数字的字符串。

A2、A3:建立结构为 (id,data) 的组表文件,使用列式存储方式。

A4:循环 6000 次,循环体B4、B5,每次生成 10 万条对应结构的记录,并追加到组表文件。

执行后,生成组表文件:id_600m.ctx

性能优化技巧 - 查找

 

代码4.2

代码4.2为组表id列建立索引。

执行后,生成组表的索引文件:id_600m.ctx__id_idx。

列存组表生成时 create() 函数加上 @r 选项,即可变为生成行存组表,其余代码无异,这里不再举例,当返回数据量较大时:

性能优化技巧 - 查找

 

代码4.3

代码4.3中,列存查询耗时和行存查询耗时,也就是A5和A9的值分别为205270和82800毫秒。

组表支持一种带值索引,即把查找字段也写入索引,这样可以不再访问原组表即返回结果。但存储空间会占用较多。

基于代码4.1的列存组表文件id_600m.ctx。

性能优化技巧 - 查找

 

代码4.4

代码4.4为组表id列建立索引,在对组表建立索引时,当 index 函数有数据列名参数,如本例 A2 中的 data,就会在建索引时把数据列 data 复制进索引。当有多个数据列时,可以写为:index(id_idx;id;data1,data2,…)。

因为在索引中做了冗余,索引文件也自然会较大,本文中测试的列存组表和索引冗余后的文件大小为:

性能优化技巧 - 查找

 

当数据复制进索引后,实际上读取时不再访问原数据文件了。

从 6 亿条数据总量中取 1 万条批量随机键值,完整的测试结果对比:

性能优化技巧 - 查找

 

5 批量键值

组表索引能够识别出contain式条件,支持批量等值查找。

性能优化技巧 - 查找

 

代码5.1

代码5.1建立组表文件id_600m.ctx,结构为(#id,data) ,包含6亿条记录,其中:

A1:包含 26 个英文字母和 10 个阿拉伯数字的字符串。

A2、A3:建立结构为 (id,data) 的组表文件,@r 选项表示使用行式存储方式。

A4:循环 6000 次,循环体B4、B5,每次生成 10 万条对应结构的记录,并追加到组表文件。

执行后,生成组表文件:id_600m.ctx。

性能优化技巧 - 查找

 

代码5.2

代码5.2为组表id列建立索引。

执行后,生成组表的索引文件:id_600m.ctx__id_idx

性能优化技巧 - 查找

 

代码5.3

代码5.3,在组表的 icursor()这个函数中,使用索引 id_idx,以条件 A2.contain(id) 来过滤组表。集算器会自动识别出 A2.contain(id) 这个条件可以使用索引,并会自动将 A2 的内容排序后从前向后查找。

进阶使用

使用排序索引多线程查找时,按键值排序分组后扔给多个线程去查询,避免两个线程中有交叉内容。同时,还可以设计成多个组表,把键值能平均分配到多个组表上并行查找。

所谓多线程并行,就是把数据分成 N 份,用 N 个线程查询。但如果只是随意地将数据分成 N 份,很可能无法真正地提高性能。因为将要查询的键值集是未知的,所以理论上也无法确保希望查找的数据能够均匀分布在每一份组表文件中。比较好的处理方式是先观察键值集的特征,从而尽可能地进行数据的均匀拆分。

如果键值数据有比较明显的业务特征,我们可以考虑按照实际业务场景使用日期、部门之类的字段来处理文件拆分。如:将属于部门 A 的 1000 条记录均分在 10 个文件中,每个文件就有 100 条记录。在利用多线程查询属于部门 A 的记录时,每个线程就会从各自对应的文件中取数相应的这 100 条记录了。

下面我们来看个实际的例子,已有数据文件multi_source.txt的结构如下:

性能优化技巧 - 查找

 

其中 type 和 id 两个字段作为联合主键确定一条记录,其中部分数据如下:

性能优化技巧 - 查找

 


性能优化技巧 - 查找

 

代码5.4

代码5.4详解:

A1:type 的枚举值组成的序列。在实际情况中,枚举列表可能来自文件或者数据库数据源。。

A2:给枚举值序列中每个 type 一个 tid。为后续的数字化主键合并做准备。

A3~A6:从 multi_source.txt 文件中获取数据,并按照 A2 中的对应关系,把 type 列的枚举串变成数字,然后将 type 和 id 进行合并后,生成新的主键 nid。

A7:使用循环函数,创建名为“键值名 _ 键值取 N 的余数 _T.ctx”的组表文件,其结构同为 (#nid,data)。

A8:用循环函数将游标数据分别追加到 N 个原组表上。比如当 N=1 时,拼出的 eval 函数参数为:channel(A4).select(nid%4==0).attach(A7(1).Append(~.cursor()))。意思是对游标 A4 创建管道,将管道中记录按键值 nid 取 4 的余数,将余数值等于 0 的记录过滤出来。attach 是对当前管道的附加运算,表示取和当前余数值对应的原组表,将当前管道中筛选过滤出的记录,以游标记录的方式追加到 A7(1),即第 1 个组表。

A9:循环游标 A6,每次获取 50 万条记录,直至 A6 游标中的数据取完。

执行后,产出 4(这时例子取 N=4)个独立的组表文件:

性能优化技巧 - 查找

 


性能优化技巧 - 查找

 

代码5.5

代码5.5,创建索引过程详解:

A1:列出满足 nid*T.ctx 的文件名(这里 * 为通配符),这里 @p 选项代表需要返回带有完整路径信息的文件名。使用 fork 执行多线程时,需要注意环境中的并行限制数是否设置合理。这里用了 4 个线程,设计器中对应的设置如下:

性能优化技巧 - 查找

 

B1:每个线程为各个组表建立对应的索引文件,最终结果如下:

性能优化技巧 - 查找

 


性能优化技巧 - 查找

 

代码5.6

代码5.6,查询过程详解:

A1:从 keys.txt 获取查询键值序列,因为只有一列结果,使用 @i 选项,将结果返回成序列:

性能优化技巧 - 查找

 

A2:把 A1 的序列按 4 的余数进行等值分组:

性能优化技巧 - 查找

 

A3、B3~B5:用 fork 函数,按等值分组后的键值对各个组表分别并行查询。这里的 fork 后面分别写了两个参数,第一个是循环函数 N.(~-1),第二个是 A2。在接下来的 B3、B4 中分别使用 A3(2) 和 A3(1) 来获取 fork 后面这两个对应顺序的参数,B4:对组表文件进行根据 B3 中的键值集进行数据筛选,B5:返回游标。由于 A3 中是多个线程返回的游标序列,所以 A6 中需要使用 conjx 对多个游标进行纵向连接。

A6~A7:将多个线程返回的游标进行纵向连接后,导出游标记录至文本文件,前几行内容如下。

性能优化技巧 - 查找


Tags:性能优化   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
对于一个新建连接,内核要发送多少个 SYN 连接请求才决定放弃。不应该大于255,默认值是5,对应于180秒左右时间。。(对于大负载而物理通信良好的网络而言,这个值偏高,可修改为2.这个值仅仅是针对对外的连接,对进来的连接,...【详细内容】
2021-12-08  Tags: 性能优化  点击:(23)  评论:(0)  加入收藏
App的性能优化,可以从多角度优化,包括App启动优化,App启动优化又分为main()函数执行前优化,main()函数执行后优化;包括界面卡顿优化,页面卡顿优化又包括CPU优化和GPU优化;包括安装包瘦...【详细内容】
2021-12-08  Tags: 性能优化  点击:(14)  评论:(0)  加入收藏
一、前言最近参加了几轮面试,发现很多5-7年工作经验的候选人在性能优化这一块,基本上只能说出传统的分析方式,例如ANR分析,是通过查看/data/anr/ 下的log,分析主线程堆栈、cpu、...【详细内容】
2021-06-17  Tags: 性能优化  点击:(149)  评论:(0)  加入收藏
MNN(Mobile Neural Network)是一个高性能、通用的深度学习框架,支持在移动端、PC端、服务端、嵌入式等各种设备上高效运行。MNN利用设备的GPU能力,全面充分“榨干”设备的GPU资源,来进行深度学习的高性能部署与训练。...【详细内容】
2021-04-20  Tags: 性能优化  点击:(228)  评论:(0)  加入收藏
一 题记最近公司项目添加新功能,上线后发现有些功能的列表查询时间很久。原因是新功能用到旧功能的接口,而这些旧接口的 SQL 查询语句关联5,6张表且编写不够规范,导致 MySQL 在...【详细内容】
2021-03-12  Tags: 性能优化  点击:(143)  评论:(0)  加入收藏
【摘要】日常生活中,我们会遇到各种各样的数据,小到公司通讯录,大到互联网用户行为分析。在进行数据分析处理的过程中,查询是必不可少的环节,如何更加高效地进行数据查询。点击:性...【详细内容】
2021-03-03  Tags: 性能优化  点击:(98)  评论:(0)  加入收藏
今天给大家分享的是MySQL性能优化,也是大数据开发指南MySQL的最后一部分。性能优化对于老刘来说,是必须掌握的一个手段,如何让自己变得更加优秀,这块内容还是好好看看!本篇内容相...【详细内容】
2021-02-07  Tags: 性能优化  点击:(162)  评论:(0)  加入收藏
说明:文章有点长,CPU性能主要观测点的理论知识搬砖堆砌得较多,主要是为了大家对CPU性能主要观测点有深入理解,这样才能在性能调优和排错的过程中把握方向,希望你能耐心读完。当...【详细内容】
2021-02-02  Tags: 性能优化  点击:(228)  评论:(0)  加入收藏
本文选自“字节跳动基础架构实践”系列文章。 “字节跳动基础架构实践”系列文章是由字节跳动基础架构部门各技术团队及专家倾力打造的技术干货内容,和大家分享团队在基础架...【详细内容】
2021-01-18  Tags: 性能优化  点击:(259)  评论:(0)  加入收藏
写在前面在像 Web 服务这样需要快速响应的应用场景中,SQL 的性能直接决定了系统是否可以使用;特别在一些中小型应用中,SQL 性能更是决定服务能否快速响应的唯一标准严格地优化...【详细内容】
2021-01-07  Tags: 性能优化  点击:(120)  评论:(0)  加入收藏
▌简易百科推荐
1增1.1【插入单行】insert [into] <表名> (列名) values (列值)例:insert into Strdents (姓名,性别,出生日期) values (&#39;开心朋朋&#39;,&#39;男&#39;,&#39;1980/6/15&#3...【详细内容】
2021-12-27  快乐火车9d3    Tags:SQL   点击:(1)  评论:(0)  加入收藏
最近发现还有不少做开发的小伙伴,在写存储过程的时候,在参考已有的不同的写法时,往往很迷茫, 不知道各种写法孰优孰劣,该选用哪种写法,以及各种写法的优缺点,本文以一个简单的查询...【详细内容】
2021-12-23  linux上的码农    Tags:sql   点击:(9)  评论:(0)  加入收藏
《开源精选》是我们分享Github、Gitee等开源社区中优质项目的栏目,包括技术、学习、实用与各种有趣的内容。本期推荐的HasorDB 是一个全功能数据库访问工具,提供对象映射、丰...【详细内容】
2021-12-22  GitHub精选    Tags:HasorDB   点击:(5)  评论:(0)  加入收藏
作者丨Rafal Grzegorczyk译者丨陈骏策划丨孙淑娟【51CTO.com原创稿件】您是否还在手动对数据库执行各种脚本?您是否还在浪费时间去验证数据库脚本的正确性?您是否还需要将...【详细内容】
2021-12-22    51CTO  Tags:Liquibase   点击:(3)  评论:(0)  加入收藏
场景描述:由于生产环境的表比较复杂,字段很多。这里我们做下简化,只为说明今天要聊的问题。有两张表 tab1,tab2: tab1 数据如下: tab2 数据如下: 然后给你看下,我用来统计 name=&#3...【详细内容】
2021-12-20  Bald    Tags:SQL   点击:(5)  评论:(0)  加入收藏
前言知识无底,学海无涯,知识点虽然简单,但是比较多,所以将MySQL的基础写出来,方便自己以后查找,还有就是分享给大家。一、SQL简述1.SQL的概述Structure Query Language(结构化查...【详细内容】
2021-12-16  谣言止于独立思考    Tags:SQL基础   点击:(13)  评论:(0)  加入收藏
前言作为一名测试工程师,工作中在对测试结果进行数据比对的时候,或多或少要和数据库打交道的,要和数据库打交道,那么一些常用的 SQL 查询语法必须要掌握。最近有部分做测试小伙...【详细内容】
2021-12-14  柠檬班软件测试    Tags:SQL   点击:(15)  评论:(0)  加入收藏
话说C是面向内存的编程语言。数据要能存得进去,取得出来,且要考虑效率。不管是顺序存储还是链式存储,其寻址方式总是很重要。顺序存储是连续存储。同质结构的数组通过其索引表...【详细内容】
2021-12-08  小智雅汇    Tags:数据存储   点击:(17)  评论:(0)  加入收藏
概述DBConvert Studio 是一款强大的跨数据库迁移和同步软件,可在不同数据库格式之间转换数据库结构和数据。它将成熟、稳定、久经考验的 DBConvert 和 DBSync 核心与改进的现...【详细内容】
2021-11-17  雪竹聊运维    Tags:数据库   点击:(26)  评论:(0)  加入收藏
一、前言 大家好,我是小诚,《从0到1-全面深刻理解MySQL系列》已经来到第四章,这一章节的主要从一条SQL执行的开始,由浅入深的解析SQL语句由客户端到服务器的完整执行流程,最...【详细内容】
2021-11-09  woaker    Tags:SQL   点击:(35)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条