当前位置:网站首页>A detailed guide to simulating latency with SQL/JDBC
A detailed guide to simulating latency with SQL/JDBC
2022-07-31 13:48:00 【DebugUsery】
I met an interesting tip,在测试一些SQL查询时,In your development environment simulation delay.Possible USES include authentication backend delay will not cause you to the front end of the paralyzed,Or user experience can still afford you,等等:
#PostgreSQL的pg_sleep()Function to simulate the slow query and evaluate its effect on the service very practical.
Wrap it as a return to a constant value of false function,You can simply add it to yourJPQL/HQL的WHERE子句中.#Hibernatehttps://t.co/4mmkl8rggQpic.twitter.com/u4qFuGAlaN
- Gunnar Morling (@gunnarmorling)2021年2月14日
这个解决方案是针对PostgreSQL和Hibernate的,Although not necessarily to be like this.此外,It USES a stored function to solvePostgreSQL中的VOID 函数的限制,But it also can use different methods to solve,Don't need any auxiliary storage directory.
In order to eliminate theHibernate的依赖,你可以直接使用NULL The predicate to usepg_sleep 函数,But don't try
select 1
from t_book
-- Don't do this!
where pg_sleep(1) is not null;
复制代码这将使每行睡眠1秒(!).As can be seen from the explain plan.Let's limit in3Line to see:
explain analyze
select 1
from t_book where pg_sleep(1) is not null limit 3;
复制代码而结果是:
Limit (cost=0.00..1.54 rows=3 width=4) (actual time=1002.142..3005.374 rows=3 loops=1)
-> Seq Scan on t_book (cost=0.00..2.05 rows=4 width=4) (actual time=1002.140..3005.366 rows=3 loops=1)
复制代码正如你所看到的,The query for3Line took about3秒.事实上,这也是GunnarIn the case of twitter happens,He just is throughID过滤的,这 "有助于 "Hide the effect.
我们可以使用Oracle所说的标量子查询缓存,In fact a scalar subquery can be reasonably expected no side effects(尽管pg_sleep ),这意味着一些RDBMSAt every time of query execution cache the results:
explain analyze
select 1
from t_book where (select pg_sleep(1)) is not null limit 3;
复制代码现在的结果是:
Limit (cost=0.01..1.54 rows=3 width=4) (actual time=1001.177..1001.178 rows=3 loops=1)
InitPlan 1 (returns $0)
-> Result (cost=0.00..0.01 rows=1 width=4) (actual time=1001.148..1001.148 rows=1 loops=1)
-> Result (cost=0.00..2.04 rows=4 width=4) (actual time=1001.175..1001.176 rows=3 loops=1)
复制代码We get now want disposable filter.然而,I don't like the hacker,Because it relies on an optimized,And the optimization is optional,Is not a formal guarantee.It may be good enough for fast simulation of delay,But in production do not rashly to rely on the optimization.
Another seems to be to make sure that the method is to use this kind of behaviorMATERIALIZED CTE:
explain with s (x) as materialized (select pg_sleep(1)) select * from t_book where (select x from s) is not null;
复制代码I now use a scalar subquery,Because I need to visitCTE,And I don't want to put it onFROM 子句中,This will affect my prediction.
计划是这样的:
Result (cost=0.03..2.07 rows=4 width=943) (actual time=1001.289..1001.292 rows=4 loops=1)
复制代码同样,Contains a disposable filter,This is what we want here.
使用基于JDBC的方法
If your application is based onJDBC的,You don't have to adjust the query to simulate the delay.You can simply acting in some wayJDBC.Let's take a look at this small program:
try (Connection c1 = db.getConnection()) {
// A Connection proxy that intercepts preparedStatement() calls
Connection c2 = new DefaultConnection(c1) {
@Override
public PreparedStatement prepareStatement(String sql)
throws SQLException {
sleep(1000L);
return super.prepareStatement(sql);
}
};
long time = System.nanoTime();
String sql = "SELECT id FROM book";
// This call now has a 1 second "latency"
try (PreparedStatement s = c2.prepareStatement(sql);
ResultSet rs = s.executeQuery()) {
while (rs.next())
System.out.println(rs.getInt(1));
}
System.out.println("Time taken: " +
(System.nanoTime() - time) / 1_000_000L + "ms");
}
复制代码在哪里?
public static void sleep(long time) {
try {
Thread.sleep(time);
}
catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
复制代码为了简单起见,这里使用了jOOQ的 [DefaultConnection](https://www.jooq.org/javadoc/latest/org.jooq/org/jooq/tools/jdbc/DefaultConnection.html)作为一个代理,Easily connect all of the methods is entrusted to some,Only allowed to rewrite the particular method.该程序的输出是:
1
2
3
4
Time taken: 1021ms
复制代码这模拟了prepareStatement() 事件的延迟.很明显,In order not to make your code messy,You can put the agent to extract some tools in.You can even in development agent所有的查询,Only according to the system properties to enable sleep call.
另外,我们也可以在executeQuery() Events on the simulated:
try (Connection c = db.getConnection()) {
long time = System.nanoTime();
// A PreparedStatement proxy intercepting executeQuery() calls
try (PreparedStatement s = new DefaultPreparedStatement(
c.prepareStatement("SELECT id FROM t_book")
) {
@Override
public ResultSet executeQuery() throws SQLException {
sleep(1000L);
return super.executeQuery();
};
};
// This call now has a 1 second "latency"
ResultSet rs = s.executeQuery()) {
while (rs.next())
System.out.println(rs.getInt(1));
}
System.out.println("Time taken: " +
(System.nanoTime() - time) / 1_000_000L + "ms");
}
复制代码Now it is in usejOOQConvenience class [DefaultPreparedStatement](https://www.jooq.org/javadoc/latest/org.jooq/org/jooq/tools/jdbc/DefaultPreparedStatement.html).如果你需要这些,只需添加jOOQOpen source version of the dependency relationship(These classes don't have anyRDBMS的特定内容),与任何基于JDBC的应用程序,包括Hibernate:
<dependency>
<groupId>org.jooq</groupId>
<artifactId>jooq</artifactId>
</dependency>
复制代码另外,If you don't need to depend on the whole,Simply copy the class sourceDefaultConnection 或DefaultPreparedStatement ,Or you just need to his agentJDBC API.
一个基于jOOQ的解决方案
如果你已经在使用jOOQ(你应该这样做!),You can more easily do this,通过实现一个 [ExecuteListener](https://www.jooq.org/doc/latest/manual/sql-execution/execute-listeners/).Our program is now looks like this:
try (Connection c = db.getConnection()) {
DSLContext ctx = DSL.using(new DefaultConfiguration()
.set(c)
.set(new CallbackExecuteListener()
.onExecuteStart(x -> sleep(1000L))
)
);
long time = System.nanoTime();
System.out.println(ctx.fetch("SELECT id FROM t_book"));
System.out.println("Time taken: " +
(System.nanoTime() - time) / 1_000_000L + "ms");
}
复制代码还是同样的结果:
+----+
|id |
+----+
|1 |
|2 |
|3 |
|4 |
+----+
Time taken: 1025ms
复制代码不同的是,Through an intercept correction,We can now add this sleep to all types of statement,包括准备好的语句、静态语句、Returns the result set statement,Or update the count,或两者都是.
边栏推荐
- Invalid bound statement (not found)出现的原因和解决方法
- MATLAB | 我也做了一套绘图配色可视化模板
- Productivity Tools and Plugins
- C# control ToolStripProgressBar usage
- 1-hour live broadcast recruitment order: industry leaders share dry goods, and enterprise registration is open丨qubit · point of view
- AI cocoa AI frontier introduction (7.31)
- IDEA connects to MySQL database and uses data
- The use of C# control CheckBox
- 网络协议及相关技术详解
- An article makes it clear!What is the difference and connection between database and data warehouse?
猜你喜欢
随机推荐
机器学习模型验证:被低估的重要一环
4.爬虫之Scrapy框架2数据解析&配置参数&数据持久化&提高Scrapy效率
滑窗法切分数据
C#控件 ToolStripProgressBar 用法
C#高级--委托
DELL SC compellent 康贝存储系统怎么抓取配置信息
Selenium自动化测试之Selenium IDE
「面经分享」西北大学 | 字节 生活服务 | 一面二面三面 HR 面
Open Inventor 10.12 重大改进--和谐版
Batch大小不一定是2的n次幂!ML资深学者最新结论
csdn发文助手问题
How IDEA runs web programs
ECCV 2022 | Robotic Interaction Perception and Object Manipulation
hyperf的启动源码分析(二)——请求如何到达控制器
Text similarity calculation (Chinese and English) detailed explanation of actual combat
报错IDEA Terminated with exit code 1
uniapp微信小程序引用标准版交易组件
A detailed explanation of the usage of Async and Await in C#
纸质说明书秒变3D动画,斯坦福大学吴佳俊最新研究,入选ECCV 2022
JSP response对象简介说明









