Skip to content

Commit 18f0171

Browse files
David-EngelVanMSFT
andauthored
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>
1 parent d8ecc24 commit 18f0171

6 files changed

Lines changed: 338 additions & 37 deletions

docs/connect/jdbc/improving-performance-and-reliability-with-the-jdbc-driver.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,17 @@ title: Improving performance and reliability
33
description: Learn about various techniques for improving application performance and reliability when using the Microsoft JDBC driver for SQL Server.
44
author: David-Engel
55
ms.author: davidengel
6-
ms.date: 05/19/2023
6+
ms.date: 12/18/2025
77
ms.service: sql
88
ms.subservice: connectivity
9-
ms.topic: conceptual
9+
ms.topic: article
1010
---
1111

1212
# Improving performance and reliability (JDBC)
1313

1414
[!INCLUDE[Driver_JDBC_Download](../../includes/driver_jdbc_download.md)]
1515

16-
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)].
1717

1818
The articles in this section describe various techniques for improving application performance and reliability when using the JDBC driver.
1919

@@ -28,8 +28,9 @@ The articles in this section describe various techniques for improving applicati
2828
|[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.|
2929
|[Sparse columns](sparse-columns.md)|Discusses the JDBC driver's support for [!INCLUDE[ssNoVersion](../../includes/ssnoversion-md.md)] sparse columns.|
3030
|[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.|
3132
|[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.|
3334

3435
## See also
3536

docs/connect/jdbc/prepared-statement-metadata-caching-for-the-jdbc-driver.md

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,59 +3,59 @@ title: Prepared statement metadata caching
33
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.
44
author: David-Engel
55
ms.author: davidengel
6-
ms.date: 08/08/2022
6+
ms.date: 12/18/2025
77
ms.service: sql
88
ms.subservice: connectivity
9-
ms.topic: conceptual
9+
ms.topic: article
1010
---
1111
# Prepared statement metadata caching for the JDBC driver
1212

1313
[!INCLUDE[Driver_JDBC_Download](../../includes/driver_jdbc_download.md)]
1414

15-
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.
1616

1717
## Batching of unprepare for prepared statements
1818

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.
2020

2121
> [!NOTE]
2222
> Users can change the default value with the following method:
23-
> setServerPreparedStatementDiscardThreshold(int value)
23+
> `setServerPreparedStatementDiscardThreshold(int value)`
2424
25-
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).
2626

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).
2828

2929
> [!NOTE]
3030
> Users can change the default behavior to the previous versions of always calling `sp_prepexec` by setting enablePrepareOnFirstPreparedStatementCall to **true** using the following method:
3131
> setEnablePrepareOnFirstPreparedStatementCall(boolean value)
3232
3333
### List of the new APIs introduced with this change, for batching of unprepare for prepared statements
3434

35-
#### SQLServerConnection
35+
#### SQLServerConnection unprepare batching
3636

3737
|New Method|Description|
3838
|-----------|-----------------|
3939
|int getDiscardedServerPreparedStatementCount()|Returns the number of currently outstanding unprepare actions.|
4040
|void closeUnreferencedPreparedStatementHandles()|Forces the unprepare requests for any outstanding discarded prepared statements to be executed.|
4141
|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().|
4242
|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.|
4545

46-
#### SQLServerDataSource
46+
#### SQLServerDataSource unprepare batching
4747

4848
|New Method|Description|
4949
|-----------|-----------------|
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.|
5454

5555
## Prepared statement metadata caching
5656

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:
5959

6060
`setStatementPoolingCacheSize(int value) //value is the desired cache size (any value bigger than 0)`
6161
`setDisableStatementPooling(boolean value) //false allows the caching to take place`
@@ -66,26 +66,27 @@ For example:
6666

6767
### List of the new APIs introduced with this change, for prepared statement metadata caching
6868

69-
#### SQLServerConnection
69+
#### SQLServerConnection metadata caching
7070

7171
|New Method|Description|
7272
|-----------|-----------------|
7373
|void setDisableStatementPooling(boolean value)|Sets statement pooling to true or false.|
7474
|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.|
7777
|int getStatementHandleCacheEntryCount()|Returns the current number of pooled prepared statement handles.|
7878
|boolean isPreparedStatementCachingEnabled()|Whether statement pooling is enabled or not for this connection.|
7979

80-
#### SQLServerDataSource
80+
#### SQLServerDataSource metadata caching
8181

8282
|New Method|Description|
8383
|-----------|-----------------|
8484
|void setDisableStatementPooling(boolean disableStatementPooling)|Sets the statement pooling to true or false|
8585
|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.|
8888

8989
## See also
9090

9191
[Improving performance and reliability with the JDBC driver](improving-performance-and-reliability-with-the-jdbc-driver.md)
92+
[Prepared statement parameter performance](prepared-statement-parameter-performance.md)

0 commit comments

Comments
 (0)