You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
New JDBC article: Prepared statement parameter performance (#36102)
* New JDBC article: Prepared statement parameter performance
* Acrolinx improvements
* Metadata updates
* Link to SQL Server, Plan Cache object article
* Apply suggestions from code review
Co-authored-by: Van To <40007119+VanMSFT@users.noreply.github.com>
---------
Co-authored-by: Van To <40007119+VanMSFT@users.noreply.github.com>
One aspect of application development that is common to all applications is the constant need to improve performance and reliability. There are many techniques to satisfy this need with the [!INCLUDE[jdbcNoVersion](../../includes/jdbcnoversion_md.md)].
16
+
One aspect of application development that's common to all applications is the constant need to improve performance and reliability. There are many techniques to satisfy this need with the [!INCLUDE[jdbcNoVersion](../../includes/jdbcnoversion_md.md)].
17
17
18
18
The articles in this section describe various techniques for improving application performance and reliability when using the JDBC driver.
19
19
@@ -28,8 +28,9 @@ The articles in this section describe various techniques for improving applicati
28
28
|[Using adaptive buffering](using-adaptive-buffering.md)|Describes an adaptive buffering feature, which is designed to retrieve any kind of large-value data without the overhead of server cursors.|
29
29
|[Sparse columns](sparse-columns.md)|Discusses the JDBC driver's support for [!INCLUDE[ssNoVersion](../../includes/ssnoversion-md.md)] sparse columns.|
30
30
|[Prepared statement metadata caching for the JDBC driver](prepared-statement-metadata-caching-for-the-jdbc-driver.md)|Discusses the techniques for improving performance with prepared statement queries.|
31
+
|[Prepared statement parameter performance](prepared-statement-parameter-performance.md)|Discusses practices and settings to consider when using prepared statements.|
31
32
|[Using bulk copy API for batch insert operation](use-bulk-copy-api-batch-insert-operation.md)|Describes how to enable Bulk Copy API for batch insert operations and its benefits.|
32
-
|[Not sending String parameters as Unicode](setting-the-connection-properties.md)|When working with **CHAR**, **VARCHAR**, and **LONGVARCHAR** data, users can set the connection property **sendStringParametersAsUnicode** to `false` for optimal performance gain.|
33
+
|[Not sending String parameters as Unicode](setting-the-connection-properties.md)|When you're working with **CHAR**, **VARCHAR**, and **LONGVARCHAR** data, set the connection property **sendStringParametersAsUnicode** to `false` for optimal performance gain.|
description: Learn how the JDBC Driver for SQL Server caches prepared statements to improve performance by minimizing calls to the database and how you can control its behavior.
4
4
author: David-Engel
5
5
ms.author: davidengel
6
-
ms.date: 08/08/2022
6
+
ms.date: 12/18/2025
7
7
ms.service: sql
8
8
ms.subservice: connectivity
9
-
ms.topic: conceptual
9
+
ms.topic: article
10
10
---
11
11
# Prepared statement metadata caching for the JDBC driver
This article provides information on the two changes that are implemented to enhance the performance of the driver.
15
+
This article provides information on two changes that enhance the performance of the driver.
16
16
17
17
## Batching of unprepare for prepared statements
18
18
19
-
Since version 6.1.6-preview, an improvement in performance was implemented through minimizing server round trips to SQL Server. Previously, for every prepareStatement query, a call to unprepare was also sent. Now, the driver is batching unprepare queries up to the threshold "ServerPreparedStatementDiscardThreshold", which has a default value of 10.
19
+
Starting with version 6.2, an improvement in performance is implemented that minimizes server round trips to SQL Server. Previously, for every prepareStatement query, a call to unprepare was also sent. Now, the driver batched unprepare queries up to the threshold `ServerPreparedStatementDiscardThreshold`, which has a default value of 10.
20
20
21
21
> [!NOTE]
22
22
> Users can change the default value with the following method:
One more change introduced from 6.1.6-preview is that before this version, the driver would always call`sp_prepexec`. Now, for the first execution of a prepared statement, driver calls `sp_executesql` and for the rest it executes `sp_prepexec` and assigns a handle to it. For more information, see [PreparedStatement metadata caching](https://github.com/Microsoft/mssql-jdbc/wiki/PreparedStatement-metadata-caching).
25
+
Before version 6.2, the driver always calls`sp_prepexec`. In 6.2 and later, for the first execution of a prepared statement, driver calls `sp_executesql` and for the rest it executes `sp_prepexec` and assigns a handle to it. For more information, see [PreparedStatement metadata caching](https://github.com/Microsoft/mssql-jdbc/wiki/PreparedStatement-metadata-caching).
26
26
27
-
Starting from the 11.2 release, following the initial `sp_executesql` call, the driver can execute either `sp_prepare` or `sp_prepexec` for additional calls, depending on the value specified in the `prepareMethod` connection string property. For more information, see [Setting the connection properties](setting-the-connection-properties.md).
27
+
Starting with version 11.2, after the initial `sp_executesql` call, the driver can execute either `sp_prepare` or `sp_prepexec` for extra calls, depending on the value specified in the `prepareMethod` connection string property. For more information, see [Setting the connection properties](setting-the-connection-properties.md).
28
28
29
29
> [!NOTE]
30
30
> Users can change the default behavior to the previous versions of always calling `sp_prepexec` by setting enablePrepareOnFirstPreparedStatementCall to **true** using the following method:
### List of the new APIs introduced with this change, for batching of unprepare for prepared statements
34
34
35
-
#### SQLServerConnection
35
+
#### SQLServerConnection unprepare batching
36
36
37
37
|New Method|Description|
38
38
|-----------|-----------------|
39
39
|int getDiscardedServerPreparedStatementCount()|Returns the number of currently outstanding unprepare actions.|
40
40
|void closeUnreferencedPreparedStatementHandles()|Forces the unprepare requests for any outstanding discarded prepared statements to be executed.|
41
41
|boolean getEnablePrepareOnFirstPreparedStatementCall()|Returns the behavior for a specific connection instance. If false, the first execution calls `sp_executesql` and doesn't prepare a statement. If a second execution happens, it calls `sp_prepare` or `sp_prepexec` and actually sets up a prepared statement handle. Later executions call `sp_execute`. This behavior relieves the need for `sp_unprepare` on prepared statement close if the statement is only executed once. The default for this option can be changed by calling setDefaultEnablePrepareOnFirstPreparedStatementCall().|
42
42
|void setEnablePrepareOnFirstPreparedStatementCall(boolean value)|Specifies the behavior for a specific connection instance. If the value is false, the first execution calls `sp_executesql` and doesn't prepare a statement. If a second execution happens, it calls `sp_prepare` or `sp_prepexec` and actually sets up a prepared statement handle. Later executions call `sp_execute`. This behavior relieves the need for `sp_unprepare` on prepared statement close if the statement is only executed once.|
43
-
|int getServerPreparedStatementDiscardThreshold()|Returns the behavior for a specific connection instance. This setting controls how many outstanding discard actions (`sp_unprepare`) there can be per connection before a call to clean up the outstanding handles on the server is executed. If the setting is <= 1, unprepare actions are executed immediately on prepared statement close. If it's set to {@literal >} 1, these calls are batched together to avoid the overhead of calling `sp_unprepare` too often. The default for this option can be changed by calling getDefaultServerPreparedStatementDiscardThreshold().|
44
-
|void setServerPreparedStatementDiscardThreshold(int value)|Specifies the behavior for a specific connection instance. This setting controls how many outstanding discard actions (`sp_unprepare`) there can be per connection before a call to clean up the outstanding handles on the server is executed. If the setting is <= 1, unprepare actions are executed immediately on prepared statement close. If it is set to > 1, these calls are batched together to avoid overhead of calling `sp_unprepare` too often.|
43
+
|int getServerPreparedStatementDiscardThreshold()|Returns the behavior for a specific connection instance. This setting controls how many outstanding discard actions (`sp_unprepare`) there can be per connection before a call to clean up the outstanding handles on the server is executed. If the setting is <= 1, unprepare actions are executed immediately on prepared statement close. When set to > 1, these calls are batched together to avoid the overhead of calling `sp_unprepare` too often. The default for this option can be changed by calling getDefaultServerPreparedStatementDiscardThreshold().|
44
+
|void setServerPreparedStatementDiscardThreshold(int value)|Specifies the behavior for a specific connection instance. This setting controls how many outstanding discard actions (`sp_unprepare`) there can be per connection before a call to clean up the outstanding handles on the server is executed. If the setting is <= 1, unprepare actions are executed immediately on prepared statement close. When set to > 1, these calls are batched together to avoid overhead of calling `sp_unprepare` too often.|
45
45
46
-
#### SQLServerDataSource
46
+
#### SQLServerDataSource unprepare batching
47
47
48
48
|New Method|Description|
49
49
|-----------|-----------------|
50
-
|void setEnablePrepareOnFirstPreparedStatementCall(boolean enablePrepareOnFirstPreparedStatementCall)|If this configuration is false, the first execution of a prepared statement calls `sp_executesql` and doesn't prepare a statement. If a second execution happens it calls `sp_prepare` or `sp_prepexec` and actually sets up a prepared statement handle. Later executions call `sp_execute`. This behavior relieves the need for `sp_unprepare` on prepared statement close if the statement is only executed once.|
51
-
|boolean getEnablePrepareOnFirstPreparedStatementCall()|If this configuration returns false, the first execution of a prepared statement calls `sp_executesql` and doesn't prepare a statement. If a second execution happens, it calls `sp_prepare` or `sp_prepexec` and actually sets up a prepared statement handle. Later executions call `sp_execute`. This behavior relieves the need for `sp_unprepare` on prepared statement close if the statement is only executed once.|
52
-
|void setServerPreparedStatementDiscardThreshold(int serverPreparedStatementDiscardThreshold)|This setting controls how many outstanding discard actions (`sp_unprepare`) there can be per connection before a call to clean up the outstanding handles on the server is executed. If the setting is <= 1, unprepare actions are executed immediately on prepared statement close. If it's set to {@literal >} 1, these calls are batched together to avoid the overhead of calling `sp_unprepare` too often|
53
-
|int getServerPreparedStatementDiscardThreshold()|This setting controls how many outstanding discard actions (`sp_unprepare`) there can be per connection before a call to clean up the outstanding handles on the server is executed. If the setting is <= 1, unprepare actions are executed immediately on prepared statement close. If it's set to {@literal >} 1, these calls are batched together to avoid the overhead of calling `sp_unprepare` too often.|
50
+
|void setEnablePrepareOnFirstPreparedStatementCall(boolean enablePrepareOnFirstPreparedStatementCall)|If this configuration is false, the first execution of a prepared statement calls `sp_executesql` and doesn't prepare a statement. If a second execution happens, it calls `sp_prepare` or `sp_prepexec` and sets up a prepared statement handle. Later executions call `sp_execute`. This behavior eliminates the need for `sp_unprepare` on prepared statement close if the statement is only executed once.|
51
+
|boolean getEnablePrepareOnFirstPreparedStatementCall()|If this configuration returns false, the first execution of a prepared statement calls `sp_executesql` and doesn't prepare a statement. If a second execution happens, it calls `sp_prepare` or `sp_prepexec` and actually sets up a prepared statement handle. Later executions call `sp_execute`. This behavior eliminates the need for `sp_unprepare` on prepared statement close if the statement is only executed once.|
52
+
|void setServerPreparedStatementDiscardThreshold(int serverPreparedStatementDiscardThreshold)|This setting controls how many outstanding discard actions (`sp_unprepare`) there can be per connection before a call to clean up the outstanding handles on the server is executed. If the setting is <= 1, unprepare actions are executed immediately on prepared statement close. When set to > 1, these calls are batched together to avoid the overhead of calling `sp_unprepare` too often|
53
+
|int getServerPreparedStatementDiscardThreshold()|This setting controls how many outstanding discard actions (`sp_unprepare`) there can be per connection before a call to clean up the outstanding handles on the server is executed. If the setting is <= 1, unprepare actions are executed immediately on prepared statement close. When set to > 1, these calls are batched together to avoid the overhead of calling `sp_unprepare` too often.|
54
54
55
55
## Prepared statement metadata caching
56
56
57
-
Starting with version 6.3.0-preview, Microsoft JDBC driver for SQL Server supports prepared statement caching. Before v6.3.0-preview, if one executes a query that has been already prepared and stored in the cache, calling the same query again won't result in preparing it. Now, the driver looks up the query in the cache and finds the handle and executes it with `sp_execute`.
58
-
Prepared Statement Metadata caching is **disabled** by default. To enable it, you need to call the following method on the connection object:
57
+
Starting with version 6.4, Microsoft JDBC driver for SQL Server supports prepared statement caching. Before version 6.4, if a query is executed that is already prepared and stored in the cache, calling the same query again doesn't require preparing again. The driver looks up the query in the cache to find the handle and executes it with `sp_execute`.
58
+
Prepared Statement Metadata caching is **disabled** by default. To enable it, call the following method on the connection object:
59
59
60
60
`setStatementPoolingCacheSize(int value) //value is the desired cache size (any value bigger than 0)`
61
61
`setDisableStatementPooling(boolean value) //false allows the caching to take place`
@@ -66,26 +66,27 @@ For example:
66
66
67
67
### List of the new APIs introduced with this change, for prepared statement metadata caching
68
68
69
-
#### SQLServerConnection
69
+
#### SQLServerConnection metadata caching
70
70
71
71
|New Method|Description|
72
72
|-----------|-----------------|
73
73
|void setDisableStatementPooling(boolean value)|Sets statement pooling to true or false.|
74
74
|boolean getDisableStatementPooling()|Returns true if statement pooling is disabled.|
75
-
|void setStatementPoolingCacheSize(int value)|Specifies the size of the prepared statement cache for this connection. A value less than 1 means no cache.|
76
-
|int getStatementPoolingCacheSize()|Returns the size of the prepared statement cache for this connection. A value less than 1 means no cache.|
75
+
|void setStatementPoolingCacheSize(int value)|Specifies the size of the prepared statement cache for this connection. A value < 1 means no cache.|
76
+
|int getStatementPoolingCacheSize()|Returns the size of the prepared statement cache for this connection. A value < 1 means no cache.|
77
77
|int getStatementHandleCacheEntryCount()|Returns the current number of pooled prepared statement handles.|
78
78
|boolean isPreparedStatementCachingEnabled()|Whether statement pooling is enabled or not for this connection.|
79
79
80
-
#### SQLServerDataSource
80
+
#### SQLServerDataSource metadata caching
81
81
82
82
|New Method|Description|
83
83
|-----------|-----------------|
84
84
|void setDisableStatementPooling(boolean disableStatementPooling)|Sets the statement pooling to true or false|
85
85
|boolean getDisableStatementPooling()|Returns true if statement pooling is disabled.|
86
-
|void setStatementPoolingCacheSize(int statementPoolingCacheSize)|Specifies the size of the prepared statement cache for this connection. A value less than 1 means no cache.|
87
-
|int getStatementPoolingCacheSize()|Returns the size of the prepared statement cache for this connection. A value less than 1 means no cache.|
86
+
|void setStatementPoolingCacheSize(int statementPoolingCacheSize)|Specifies the size of the prepared statement cache for this connection. A value < 1 means no cache.|
87
+
|int getStatementPoolingCacheSize()|Returns the size of the prepared statement cache for this connection. A value < 1 means no cache.|
88
88
89
89
## See also
90
90
91
91
[Improving performance and reliability with the JDBC driver](improving-performance-and-reliability-with-the-jdbc-driver.md)
0 commit comments