Source code: https://raw.githubusercontent.com/luodonghua/PostgreSQL/main/Development/Java/JdbcPreparedPlanCacheModeDemo.java
Summary
Observations:
- During testing, the first time execution with id=1000 is much more expensive comparing to subsequent execution (483 ms vs 0.7 ms), although same plan used.
- In the situation with "prepared statements", the value for
prepareThreshold=n
and plan_cache_mode=auto
, after n+5-1
executions, generic plan could be used if " its cost is not so much higher than the average custom-plan cost". (Ref: https://www.postgresql.org/docs/current/sql-prepare.html) plan_cache_mode
only affects prepared statements, has no effect on literal queries.- To ensure optimizer always pick the best plan,
plan_cache_mode=force_custom_plan
produces consistent plans.
Prepare Statements:
PreparedStatement ps = conn.prepareStatement("SELECT * FROM t WHERE id = ?");
ps.setInt(1, 1);
ps.executeQuery().close();
ps.setInt(1, 2);
ps.executeQuery().close();
ps.setInt(1, 3);
ps.executeQuery().close();
ps.setInt(1, 4);
ps.executeQuery().close();
ps.setInt(1, 5);
ps.executeQuery().close();
ps.setInt(1, 6);
ps.executeQuery().close();
ps.setInt(1, 1000);
ps.executeQuery().close();
ps.setInt(1, 7);
ps.executeQuery().close();
ps.setInt(1, 1000);
ps.executeQuery().close();
Result
Config | 1 | 2 | 3 | 4 | 5 | 6 | 1000 | 7 | 1000 |
---|
1.PrepareThreshold5CacheModeAuto | BIS | IS | IS | IS | IS | IS | SEQ | IS | SEQ |
2.PrepareThreshold5CacheModeForceCustom | IS | IS | IS | IS | IS | IS | SEQ | IS | SEQ |
3.PrepareThreshold5CacheModeForceGeneric | IS | IS | IS | IS | IS | IS | IS | IS | IS |
4.PrepareThreshold10CacheModeAuto | IS | IS | IS | IS | IS | IS | SEQ | IS | SEQ |
5.PrepareThreshold10CacheModeForceCustom | IS | IS | IS | IS | IS | IS | SEQ | IS | SEQ |
6.PrepareThreshold10CacheModeForceGeneric | IS | IS | IS | IS | IS | IS | IS | IS | IS |
7.PrepareThreshold1CacheModeAuto | IS | IS | IS | IS | IS | IS | IS | IS | IS |
8.PrepareThreshold1CacheModeForceCustom | IS | IS | IS | IS | IS | IS | SEQ | IS | SEQ |
9.PrepareThreshold1CacheModeForceGeneric | IS | IS | IS | IS | IS | IS | IS | IS | IS |
- BIS: Bitmap Index Scan
- IS: Index Scan
- SEQ: Seq Scan
Prepare Statements Starts with 1000
PreparedStatement ps = conn.prepareStatement("SELECT * FROM t WHERE id = ?");
ps.setInt(1, 1000);
ps.executeQuery().close();
ps.setInt(1, 2);
ps.executeQuery().close();
ps.setInt(1, 3);
ps.executeQuery().close();
ps.setInt(1, 4);
ps.executeQuery().close();
ps.setInt(1, 5);
ps.executeQuery().close();
ps.setInt(1, 6);
ps.executeQuery().close();
ps.setInt(1, 1000);
ps.executeQuery().close();
ps.setInt(1, 7);
ps.executeQuery().close();
ps.setInt(1, 1000);
ps.executeQuery().close();
Result
Config | 1000 | 2 | 3 | 4 | 5 | 6 | 1000 | 7 | 1000 |
---|
10.PrepareThreshold5CacheModeAuto | SEQ | IS | IS | IS | IS | IS | SEQ | IS | SEQ |
11.PrepareThreshold5CacheModeForceCustom | SEQ | IS | IS | IS | IS | IS | SEQ | IS | SEQ |
12.PrepareThreshold5CacheModeForceGeneric | IS | IS | IS | IS | IS | IS | IS | IS | IS |
13.PrepareThreshold10CacheModeAuto | SEQ | IS | IS | IS | IS | IS | SEQ | IS | SEQ |
14.PrepareThreshold10CacheModeForceCustom | SEQ | IS | IS | IS | IS | IS | SEQ | IS | SEQ |
15.PrepareThreshold10CacheModeForceGeneric | IS | IS | IS | IS | IS | IS | IS | IS | IS |
16.PrepareThreshold1CacheModeAuto | SEQ | IS | IS | IS | IS | IS | IS | IS | IS |
17.PrepareThreshold1CacheModeForceCustom | SEQ | IS | IS | IS | IS | IS | SEQ | IS | SEQ |
18.PrepareThreshold1CacheModeForceGeneric | IS | IS | IS | IS | IS | IS | IS | IS | IS |
- BIS: Bitmap Index Scan
- IS: Index Scan
- SEQ: Seq Scan
Statements:
Statement stmt = conn.createStatement();
stmt.execute("SELECT * FROM t WHERE id = 1");
stmt.execute("SELECT * FROM t WHERE id = 2");
stmt.execute("SELECT * FROM t WHERE id = 3");
stmt.execute("SELECT * FROM t WHERE id = 4");
stmt.execute("SELECT * FROM t WHERE id = 5");
stmt.execute("SELECT * FROM t WHERE id = 6");
stmt.execute("SELECT * FROM t WHERE id = 1000");
stmt.execute("SELECT * FROM t WHERE id = 7");
stmt.execute("SELECT * FROM t WHERE id = 1000");
stmt.close();
Config | 1 | 2 | 3 | 4 | 5 | 6 | 1000 | 7 | 1000 |
---|
19.PrepareThreshold5CacheModeAuto | IS | IS | IS | IS | IS | IS | SEQ | IS | SEQ |
20.PrepareThreshold5CacheModeForceCustom | IS | IS | IS | IS | IS | IS | SEQ | IS | SEQ |
21.PrepareThreshold5CacheModeForceGeneric | IS | IS | IS | IS | IS | IS | SEQ | IS | SEQ |
22.PrepareThreshold10CacheModeAuto | IS | IS | IS | IS | IS | IS | SEQ | IS | SEQ |
23.PrepareThreshold10CacheModeForceCustom | IS | IS | IS | IS | IS | IS | SEQ | IS | SEQ |
24.PrepareThreshold10CacheModeForceGeneric | IS | IS | IS | IS | IS | IS | SEQ | IS | SEQ |
25.PrepareThreshold1CacheModeAuto | IS | IS | IS | IS | IS | IS | SEQ | IS | SEQ |
26.PrepareThreshold1CacheModeForceCustom | IS | IS | IS | IS | IS | IS | SEQ | IS | SEQ |
27.PrepareThreshold1CacheModeForceGeneric | IS | IS | IS | IS | IS | IS | SEQ | IS | SEQ |
- BIS: Bitmap Index Scan
- IS: Index Scan
- SEQ: Seq Scan
Statements:
Statement stmt = conn.createStatement();
stmt.execute("SELECT * FROM t WHERE id = 1000");
stmt.execute("SELECT * FROM t WHERE id = 2");
stmt.execute("SELECT * FROM t WHERE id = 3");
stmt.execute("SELECT * FROM t WHERE id = 4");
stmt.execute("SELECT * FROM t WHERE id = 5");
stmt.execute("SELECT * FROM t WHERE id = 6");
stmt.execute("SELECT * FROM t WHERE id = 1000");
stmt.execute("SELECT * FROM t WHERE id = 7");
stmt.execute("SELECT * FROM t WHERE id = 1000");
stmt.close();
Config | 1000 | 2 | 3 | 4 | 5 | 6 | 1000 | 7 | 1000 |
---|
28.PrepareThreshold5CacheModeAuto | SEQ | IS | IS | IS | IS | IS | SEQ | IS | SEQ |
29.PrepareThreshold5CacheModeForceCustom | SEQ | IS | IS | IS | IS | IS | SEQ | IS | SEQ |
30.PrepareThreshold5CacheModeForceGeneric | SEQ | IS | IS | IS | IS | IS | SEQ | IS | SEQ |
31.PrepareThreshold10CacheModeAuto | SEQ | IS | IS | IS | IS | IS | SEQ | IS | SEQ |
32.PrepareThreshold10CacheModeForceCustom | SEQ | IS | IS | IS | IS | IS | SEQ | IS | SEQ |
33.PrepareThreshold10CacheModeForceGeneric | SEQ | IS | IS | IS | IS | IS | SEQ | IS | SEQ |
34.PrepareThreshold1CacheModeAuto | SEQ | IS | IS | IS | IS | IS | SEQ | IS | SEQ |
35.PrepareThreshold1CacheModeForceCustom | SEQ | IS | IS | IS | IS | IS | SEQ | IS | SEQ |
36.PrepareThreshold1CacheModeForceGeneric | SEQ | IS | IS | IS | IS | IS | SEQ | IS | SEQ |
- BIS: Bitmap Index Scan
- IS: Index Scan
- SEQ: Seq Scan