Jak*_*ins 6 java node.js express spring-data-jpa spring-boot
我创建了两个基本项目来比较框架。在最近的工作项目上进行开发时,我注意到使用 Spring Data JPA 时查询运行速度非常慢。
我设置了一个小实验来测试 NodeJS 与 Spring Boot,以确定它是数据库还是框架。
SELECT * FROM v$version;
Oracle Database 12c 企业版 12.1.0.2.0 版 - 64 位生产
该数据库位于 400 英里外的另一个设施中,导致大约 60-80 毫秒的网络延迟。
-------------- -------- ------------
ID NOT NULL NUMBER
AR VARCHAR2(10)
MOD_TIME DATE
MOD_UID VARCHAR2(10)
ACTIVE_IND VARCHAR2(1)
WORK_ID NUMBER
Run Code Online (Sandbox Code Playgroud)
在我们的测试环境中,该数据库中有 4533 条记录。我们有大约 9000 个在生产中。本实验将使用测试环境运行。
弹簧设置:
start.spring.io 并选择 Web ,JPA, Oracle Driver, lombok
创建实体类
@Entity
@Table(name = "t_test")
@Data
public class TTest implements Serializable {
private static final long serialVersionUID = 3305605889880335034L;
@Id
@Column(name = "ID")
private int id;
@Column(name = "AR")
private String ar;
@Column(name = "mod_time")
private Timestamp modTime;
@Column(name = "mod_uid")
private String modId;
@Column(name = "active_ind")
private String activeInd;
@Column(name = "work_id")
private Integer wid;
}
Run Code Online (Sandbox Code Playgroud)
然后是一个简单的存储库来运行 findAll() 查询
@Repository
public interface TTestRepo extends JpaRepository<TTest, Integer> {}
Run Code Online (Sandbox Code Playgroud)
最后是一个控制器
@RestController
@Slf4j
public class TestController {
@Autowired
TTestRepo repo;
@GetMapping("/testDb")
public List<TTest> testDb(){
return repo.findAll();
}
}
Run Code Online (Sandbox Code Playgroud)
我使用 application.properties 连接到数据库
spring.datasource.url=blah
spring.datasource.username=blah
spring.datasource.password=blah
spring.datasource.driver-class-name=oracle.jdbc.driver.OracleDriver
spring.jpa.show-sql=true
logging.level.org.hibernate.SQL=DEBUG
Run Code Online (Sandbox Code Playgroud)
NodeJS 设置
只是一个安装了 oracledb 的简单 Express 应用程序。
const express = require('express')
var oracledb = require('oracledb')
oracledb.getConnection(
{
//removed for obvious reasons
},
function(err, connection) {
console.log('trying to connect...')
if (err) {
console.error(err)
return
}
global.connection = connection
}
)
global.transformResults = function transformResults(result) {
let finalResults = []
let obj = {}
result.rows.forEach((row) => {
result.metaData.forEach( (meta, j) => {
obj[meta.name] = row[j]
})
finalResults.push(obj)
obj = {}
})
return finalResults
}
// Create express instnace
const app = express()
// Require API routes
const users = require('./routes/users')
// Import API Routes
app.use(users)
// Export the server middleware
module.exports = {
path: '/api',
handler: app
}
Run Code Online (Sandbox Code Playgroud)
users.js 只是我运行查询的路由器或休息端点
const { Router } = require("express");
const router = Router();
router.get("/testDb", async function(req, res, next) {
connection.execute(
"SELECT * from t_test",
function(err, result) {
if (err) {
console.error(err)
return
}
res.json(transformResults(result));
}
)
});
module.exports = router;
Run Code Online (Sandbox Code Playgroud)
基准测试
对于 Spring Data JPA,我做了这个基准测试
/**
* @author Jake Perkins on 11/20/2019
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class BenchMark {
@Autowired
TestController controller;
@Test
public void benchmarkDb(){
int testLength = 100;
long startTime = System.currentTimeMillis();
for(int i = 0; i < testLength; i++){
controller.testDb(); //Measure execution time for this method
}
long endTime = System.currentTimeMillis();
long durationInMillis = (endTime - startTime); //Total execution time in milliseconds
BigDecimal averageInSeconds = BigDecimal.valueOf(durationInMillis/testLength).movePointLeft(3);
System.out.println(averageInSeconds);
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
23.463
Run Code Online (Sandbox Code Playgroud)
NodeJS 基准测试使用以毫秒为单位的开始时间和以毫秒为单位的结束时间之间的差异计算类似。
实验结果
我在两种环境中都运行了 100 次查询,并收集了以下平均时间。
Spring Boot:23.4 秒
NodeJS:2.9 秒
Oracle SQL 开发人员:2.6 秒
在收集 4533 条记录(在我的特定情况下)时,Spring Boot 花费的时间大约是 node JS 的 8 倍。为什么?
我的第一个想法是数组获取大小或预取大小的差异。这可能会对 WAN 上的多行查询性能产生重大影响。
\n\n来自Oracle\xc2\xae 数据库 JDBC 开发人员指南:
\n\n\n\n\n\n\n默认情况下,当 Oracle JDBC 运行查询时,它从数据库游标一次检索\n 10 行的结果集
\n
\n\n\n此属性设置用于从 Oracle 数据库获取查询行的内部缓冲区的大小。更改它可能会影响查询性能,但不会影响返回到应用程序的行数。
\n\n默认值为 100。
\n
您可以oracledb.fetchArraySize
在 Node.js 应用程序中轻松更改为 10,看看性能是否会下降到 Spring 的水平。
您可以增加大小,看看是否可以获得更好的性能。
\n 归档时间: |
|
查看次数: |
1465 次 |
最近记录: |