当前位置:网站首页>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,或两者都是.
边栏推荐
- C#高级--委托
- Miller_Rabin Miller Rabin probability sieve [template]
- Install the latest pytorch gpu version
- Batch大小不一定是2的n次幂!ML资深学者最新结论
- Comparison of Optical Motion Capture and UWB Positioning Technology in Multi-agent Cooperative Control Research
- go使用makefile脚本编译应用
- C#控件ListView用法
- 技能大赛训练题:交换机虚拟化练习
- C# Get network card information NetworkInterface IPInterfaceProperties
- 文本相似度计算(中英文)详解实战
猜你喜欢
随机推荐
Shang Silicon Valley-JVM-Memory and Garbage Collection (P1~P203)
基于高阶微分器的无模型滑模控制器及其在自动电压调节器中的应用
CodeIgniter 打开错误日志
How to quickly split and merge cell data in Excel
1小时直播招募令:行业大咖干货分享,企业报名开启丨量子位·视点
csdn发文助手问题
技能大赛训练题:域用户和组织单元的创建
pytorch gpu版本安装最新
【牛客刷题-SQL大厂面试真题】NO3.电商场景(某东商城)
C#控件CheckBox的使用
清除浮动的四种方式及其原理理解
战略进攻能力的重要性,要远远高于战略防守能力
CLion用于STM32开发
Golang - gin - pprof - use and safety
ECCV 2022 | Robotic Interaction Perception and Object Manipulation
Buffer 与 拥塞控制
Error: npm ERR code EPERM
20.nn.Module
LeetCode·每日一题·1161.最大层内元素和·层次遍历
Open Inventor 10.12 重大改进--和谐版









