了解如何通过使用标准Java 8流和Speedment的In-JVM-Memory加速器将分析数据库应用程序加速1000倍。

Web和移动应用程序有时会很慢,因为后备数据库很慢和/或与数据库的连接施加了延迟。 现代UI和交互式应用程序需要快速后端,并且理想情况下没有可观察到的延迟,否则用户将继续使用其他服务,或者只会感到厌倦并完全停止使用该服务。

在本文中,我们将学习如何使用标准Java 8流和Speedment的in-JVM内存加速技术将分析数据库应用程序加速几个数量级。 最后,我们将运行具有代表性基准的JMH测试服,这些基准表明加速因子超过1,000倍。

以流查看数据库

速度是基于ORM的现代流,这意味着表被视为标准Java 8流。 在本文中,我们将使用“ Sakila”数据库,这是一个开放源代码示例数据库,可直接从Oracle 这里获得 。 Sakila示例数据库包含电影,演员等。 这是来自数据库的Java 8流的样子:

List<Film> secondPage = films.stream().filter(Film.RATING.equal("PG-13")).sorted(Film.TITLE.comparator()).skip(50).limit(50).collect(Collectors.toList());

该流将仅过滤出评级为“ PG-13”的电影,然后按电影标题对其余电影进行排序。 之后,跳过前50部电影,然后将接下来的50部电影收集到列表中。 因此,我们获得了按标题顺序排列的所有PG-13电影的第二页。 通常,我们还需要知道总共有多少部电影的评级为“ PG-13”,以便在我们的应用程序中显示正确缩放的滚动条。 可以这样完成:

long count = films.stream().filter(Film.RATING.equal("PG-13")).count();

使用数据库

Speedment将自动将Streams呈现为SQL。 这样,我们可以保持在纯类型安全的Java环境中,而不必编写SQL代码。 通过启用日志记录,我们可以看到第一个分页流将呈现给以下SQL查询(假设我们正在使用MySQL):

SELECT`film_id`,`title`,`description``release_year`,`language_id`,`original_language_id`,`rental_duration`,`rental_rate`,`length`,`replacement_cost`,`rating`,`special_features`,`last_update`
FROM `sakila`.`film`
WHERE (`sakila`.`film`.`rating`  = ? COLLATE utf8_bin)
ORDER BY `sakila`.`film`.`title` ASC
LIMIT ? OFFSET ?values:[PG-13, 50, 50]

第二个计数流将呈现为:

SELECT COUNT(*) FROM (SELECT`film_id`,`title`,`description``release_year`,`language_id`,`original_language_id`,`rental_duration`,`rental_rate`,`length`,`replacement_cost`,`rating`,`special_features`,`last_update`FROM`sakila`.`film` WHERE (`sakila`.`film`.`rating`  = ? COLLATE utf8_bin)
) AS Avalues:[PG-13]

因此,将流操作呈现为有效的SQL。 当在具有MySQL标准服务器配置的笔记本电脑类计算机上并行运行一千个查询时,它们分别在700毫秒和175毫秒的总延迟中完成。 如果您在考虑第二条SQL语句的效率如何,那么事实是数据库将基本上可以消除内部选择。

使用JVM中的内存加速

现在到有趣的部分。 让我们在应用程序中激活Speedment中的JVM内存中加速组件,称为DataStore。 这是通过以下方式完成的:

SakilaApplication app = new SakilaApplicationBuilder().withPassword("sakila-password")// Activate DataStore.withBundle(DataStoreBundle.class).build();// Load a snapshot of the database into off heap memoryapp.get(DataStoreComponent.class).ifPresent(DataStoreComponent::load);

启动应用程序时,数据库的快照被拉入JVM,并以堆外方式存储。 由于数据是非堆存储的,因此数据不会影响垃圾回收,并且数据量仅受可用RAM的限制。 如果有那么多的可用RAM,没有什么可以阻止我们加载TB的数据。

如果现在再次运行同一应用程序,则将获得22毫秒和1毫秒的总延迟。 这意味着等待时间分别减少了30倍和170倍。 必须说是一个重大改进。 但是,它还在变得更好。

使用JVM中的内存加速和Json

REST和JSON通常用于为最近请求数据的客户端提供服务。 Speedment有一个特殊的收集器,可以使用所谓的就地反序列化来收集JSON数据,从而仅从收集器内存中反序列化收集器所需的字段。 我们可以通过首先在pom文件中添加依赖项来依赖Json插件:

<dependency><groupId>com.speedment.enterprise.plugins</groupId><artifactId>json-stream</artifactId><version>${speedment.enterprise.version}</version></dependency>

然后,我们将插件安装在ApplicationBuilder中,如下所示:

SakilaApplication app = new SakilaApplicationBuilder().withPassword("sakila-password").withBundle(DataStoreBundle.class)// Install the Json Plugin.withBundle(JsonBundle.class).build();

如果我们只希望在json输出中使用Film字段“ title”,“ rating”和“ length”,则可以创建一个Json编码器,如下所示:

final JsonComponent json = app.getOrThrow(JsonComponent.class);final JsonEncoder<Film> filmEncoder = json.<Film>emptyEncoder().put(Film.TITLE).put(Film.RATING).put(Film.LENGTH).build();

该解码器是不可变的,可以在我们的应用程序中反复使用:

String json = films.stream().filter(Film.RATING.equal("PG-13")).sorted(Film.TITLE.comparator()).skip(50 * pageNo).limit(50).collect(JsonCollectors.toList(filmEncoder));

与处理整个实体相比,这为我们提供了2的额外加速因子。 JsonComponent可以做的不仅仅是将事情收集到列表中。 例如,它还可以使用就地反序列化来创建聚合。

使用In-JVM-Memory加速运行您自己的项目

自己尝试在JVM-Memory中加速很容易。 在这里可以找到免费的初始化器。 只需在所需的数据库类型中打勾,您便会自动为您生成一个POM和一个应用程序模板。 您还需要许可证密钥才能运行。 只需在同一页面上单击“请求免费试用许可证密钥”即可获得一个。 如果您需要更多帮助来设置项目,请查看Speedment GitHub页面或浏览手册 。

Real的速度有多快?

Speedment支持多种数据库类型,包括Oracle,MySQL,MariaDB,PostgreSQL,Microsoft SQL Server,DB2和AS400。 Speedment也可以使用Hadoop使用的Avro文件。 在此示例中,我们将运行MySQL。

众所周知,在Java应用程序中测试性能非常困难。 使用JMH框架,我编写了许多典型的应用程序,每个应用程序都运行了数十万次,并将纯MySQL和MySQL与Speedment的in-JVM加速器的结果进行了比较。 以下性能数据以每秒操作数(越高越好)的形式给出。

基准测试 纯MySQL 具有Speedment in-JVM的MySQL 加速因子
数一数 5,324 43,615,967 8,000
用过滤器计数 5,107 2,465,928 400
筛选 449 597,702 1,300
排序 109 171,304 1,500
分页 1,547 1,443,015 900
遍历所有 108 5,556 50
聚合 117 167,728 1,400
聚集过滤器 453 608,763 1,300

可以看出,在大多数情况下,带有Speedment In-JVM加速器的MySQL比纯MySQL的性能高出1,000倍。 观察到的最小加速因子是50倍,这仍然非常好。

测试环境

MySQL,5.7.16标准安装,MySQL JDBC驱动程序5.1.42,Oracle Java 1.8.0_131,Speedment Enterprise 1.1.10,macOS Sierra 10.12.6,Macbook Pro 2.2 GHz i7(2015年中),16 GB RAM。

基准代码

以下是基准代码外观的一些示例。 完整的基准测试应用程序可以在GitHub上找到 。 我鼓励您克隆它并运行它,以查看您自己的目标计算机上的加速因素。

@Benchmarkpublic String paging() {return films.stream().filter(Film.RATING.equal("PG-13")).skip(50).limit(50).collect(filmCollector);}@Benchmarkpublic String aggregationWithFilter() {return films.stream().filter(Film.RATING.equal("PG-13")).collect(sumLengthCollector);}

需要多少RAM?

速度通常比数据库本身更有效地将数据存储在RAM中。 基准测试中的Sakila数据库在磁盘上占用6.6 MB,但Speedment仅使用3 MB内存。 考虑到默认情况下,Speedment对所有列进行索引,而数据库仅对少数列进行索引,因此Speedment显着提高了内存效率。

加载数据需要多长时间?

Sakila数据库在不到1秒的时间内就被Speedment加载并建立索引。 Speedment可以在后台从数据库刷新数据,并且可以跟踪针对哪个数据库快照版本(MVCC)运行的流。

我自己的应用程序可以运行多少速度?

任何人都可以猜测,在特定项目中可以减少多少延迟。 是x10,x50,x100还是更多? 抓住机会,找出自己的项目可以提高多少速度!

旋转一下

在GitHub上了解有关Speedment的更多信息,并使用Speedment Initializer启动您自己的项目,并记住勾选“启用内存中加速”,并使用初始化程序也获得免费的评估许可证密钥。 在此处浏览有关Speedment in-JVM加速器的手册部分,或使用我的Twitter句柄@PMinborg

翻译自: https://www.javacodegeeks.com/2017/09/need-speed-access-existing-data-1000x-faster.html

对速度的需求,访问现有数据的速度提高了1000倍相关推荐

  1. 需求调研 现有系统梳理_对速度的需求,访问现有数据的速度提高了1000倍

    需求调研 现有系统梳理 了解如何通过使用标准Java 8流和Speedment的In-JVM-Memory加速器将分析数据库应用程序加速1000倍. Web和移动应用程序有时会很慢,因为后备数据库很慢 ...

  2. 千万级数据库使用索引查询速度更慢的疑惑-数据回表问题

    环境 数据库:TiDB数据库(和mysql数据库极其相似的数据库) 表名:index_basedata 表数据:13 000 000条数据 表索引:包含一个普通索引,索引列 "year&qu ...

  3. 刀片服务器在现有数据中心的应用策略

    刀片服务器运行环境的功率密度实际上超过了以往任何数据中心的功率和散热能力.在现有的数据中心中安装刀片服务器无疑将会带来一系列的挑战,也会出现多种安装方案,令你难以抉择.如何对这些方案进行评估,择取最佳 ...

  4. redshift 数据仓库_您如何使用Amazon Redshift Spectrum访问“暗数据”

    redshift 数据仓库 by Lars Kamp 通过拉斯·坎普 您如何使用Amazon Redshift Spectrum访问"暗数据" (How you can acces ...

  5. redis主从复制,复制功能是高可用Redis的基础,为满足故障恢复和负载均衡等需求把Redis数据复制多个副本部署到其他机器;如何实现redis的主从复制模式以及主从复制模式下常见的运维问题;

    目录 一.如何使用redis主从复制模式 1.建立复制 2.断开复制 3.安全性 4.只读模式 5.传输延迟 二.Redis的复制拓扑结构 1.一主一从结构 2.一主多从结构 3.树状主从结构 三.主 ...

  6. 一个简单的更改让PyTorch读取表格数据的速度提高20倍:可大大加快深度学习训练的速度...

    来源:DeepHub IMBA 本文约3000字,建议阅读5分钟 我在PyTorch中对表格的数据加载器进行的简单更改如何将训练速度提高了20倍以上,而循环没有任何变化! 深度学习:需要速度 在训练深 ...

  7. 1.1 - C#语言习惯 - 使用属性而不是可访问的数据成员

    属性一直是C#语言中的一等公民.自1.0版本以来,C#对属性进行了一系列的增强,让其表达能力不管提高.你甚至可以为setter和getter指定不同的访问权限. 隐式属性也极大降低了声明属性时的工作量 ...

  8. extjs 表格数据重新加载_一个简单的更改让PyTorch读取表格数据的速度提高20倍:可大大加快深度学习训练的速度...

    来源:DeepHub IMBA 本文约3000字,建议阅读5分钟我在PyTorch中对表格的数据加载器进行的简单更改如何将训练速度提高了20倍以上,而循环没有任何变化! 深度学习:需要速度 在训练深度 ...

  9. 荐读|属性与可直接访问的数据成员之间应该如何选

    写在前面 在书写C#代码的时候你是否有过这样的经历:经常混用属性以及公有的数据成员.毕竟他们的用法基本一致,对于使用来说好像没什么区别啊.其实我也经常使用类的公有的数据成员来定义一些常量,为了简单,在 ...

最新文章

  1. MySQL中的共享锁与排他锁
  2. 【转载】机器学习领域的大家
  3. java垃圾回收机制串行_Java垃圾回收机制
  4. IOS7的一个神奇的Bug
  5. boost::hana::slice用法的测试程序
  6. [译]Java 垃圾回收介绍
  7. linux系统atom安装教程,Ubuntu/Linux Mint上安装Atom文本编辑器
  8. PowerShell+you-get批量下载B站视频
  9. JavaScript对象学习笔记
  10. mysql 在线备份脚本,MySQL备份脚本
  11. ORACLE数据库事务隔离级别
  12. apache配置多https域名对应单个证书和多个不同的https域名对应多个不同的证书
  13. forward计算机语言,const_forward在C中的可选实现中做了什么?
  14. 非平衡电桥电阻计算_用非平衡电桥如何测量电阻_非平衡电桥测量电阻详解
  15. PTA乙级1014(python3)
  16. 安卓手机还有这么多神仙玩法,关键只有少数人知道
  17. 代驾APP小程序源码交付 所需功能大全
  18. 转至老熊三分地--inside sqlplus prelim
  19. job全异常 mapreduce_eclipse 运行MapReduce程序错误异常汇总(解决Map not fount)
  20. 码分多址CDMA及计算(简单易懂)

热门文章

  1. Java虚拟机必学之四大知识要点,附学习资料
  2. 10亿个数中找出最大的10000个数
  3. MySQL date_sub()函数
  4. Java并发包:ConcurrentMap
  5. 115个Java面试题和答案——终极列表(下)
  6. 若依前后端部署之后验证码不显示
  7. 优秀学生专栏——董超
  8. javaWeb服务详解(含源代码,测试通过,注释) ——Emp的Service层
  9. r2dbc_使用Spring Data R2DBC进行异步RDBMS访问
  10. java 方法 示例_Java 9示例–收集的工厂方法–创建不可修改的列表,集合和映射...