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
Copy file name to clipboardExpand all lines: devdoc/jdp/jdp-2025-03-implement-protocol-19.adoc
+24-23Lines changed: 24 additions & 23 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -15,24 +15,25 @@
15
15
== Context
16
16
17
17
Firebird 5.0.3 introduces protocol version 19, which will provide a significant performance improvement for small blobs.
18
-
This improvement is achieved by sending small blobs inline during the response to cursor fetch, removing the need to explicitly open and request the blobs one by one.
18
+
This improvement is achieved by sending small blobs inline during the response to a cursor fetch, removing the need to explicitly open and request the blobs one by one.
19
19
20
20
Overview of protocol changes:
21
21
22
22
* The upper limit for inline blob length is 65535 bytes (0xFFFF);
23
23
this includes segment length(s).
24
24
* `op_execute`/`op_execute2` has an extra (unsigned) int `p_sqldata_inline_blob_size` with the requested inline blob size sent immediately after `p_sqldata_cursor_flags`
25
25
* We don't cover the changes for `op_exec_immediate2` as Jaybird doesn't implement it
26
-
* The response to `op_execute2` will have zero or more `op_inline_blob` (114) responses before the `op_sql_response` packet
27
-
* The response to `op_fetch` will have zero or more `op_inline_blob` (114) responses before each `op_fetch_response`
26
+
* The response to `op_execute2` will have zero or more `op_inline_blob` `(114`) responses before the `op_sql_response` packet
27
+
* The response to `op_fetch`/`op_fetch_scroll` will have zero or more `op_inline_blob` (`114`) responses before each `op_fetch_response`
28
28
* The `op_line_blob` response is the `P_INLINE_BLOB` message with the following payload:
29
29
** `p_tran_id` int (formally short): transaction handle
30
30
** `p_blob_id` long: blob id
31
31
** `p_blob_info` buffer: blob info with (`isc_info_blob_num_segments`, `isc_info_blob_max_segment`, `isc_info_blob_total_length`, `isc_info_blob_type`, `isc_info_end`)
32
32
** `p_blob_data` buffer: blob data (including segment lengths!)
33
-
* Two DPB items were added, `isc_dpb_max_blob_cache_size` (159) and `isc_dpb_max_inline_blob_size` (160), which are used to configure the client.
33
+
* Two DPB items were added, `isc_dpb_max_blob_cache_size` (`159`) and `isc_dpb_max_inline_blob_size` (`160`), which are used to configure the client.
34
34
35
35
The JDBC implementation in Jaybird requests blobs with a blob parameter buffer that should match the "`normal`" blob, but API-wise on the `FbDatabase` side, it could be anything.
36
+
The fbclient implementation will not use the cached inline blob if any blob parameter buffer is passed.
36
37
37
38
== Decision
38
39
@@ -41,7 +42,7 @@ As Jaybird 5 is the "`long-term support`" version for Java 8, and this is a cons
41
42
=== Decision details
42
43
43
44
* Two connection properties, `maxBlobCacheSize` and `maxInlineBlobSize`, are added and associated with their respective DPB items.
44
-
That way the implementation will also support configuring inline blobs for native connections (when using fbclient 5.0.3 or higher).
45
+
That way, the implementation will also support configuring inline blobs for native connections (when using fbclient 5.0.3 or higher).
45
46
** If `maxInlineBlobSize` is not explicitly set, it will use a default of 64 KiB for pure Java connections;
46
47
for native connections, it will use the fbclient default (currently also 64 KiB). +
47
48
** Setting `maxInlineBlobSize` to `0` will disable inline blobs
@@ -50,26 +51,19 @@ for native connections, it will use the fbclient default (currently also 10 MiB)
50
51
** Setting `maxBlobCacheSize` to `0` will *not* disable inline blobs.
51
52
* The received inline blobs will be registered on the `FbWireDatabase` instance in a blob cache, to be returned from `createBlobForInput` as an inline blob instance implementing `FbWireBlob`.
52
53
** The blob cache tracks memory use based on the blob length and will hold the blob data *without* segment lengths.
53
-
If the blob cache exceeds the `maxInlineBlobSize`, the inline blob will be thrown away.
54
-
** Once requested, the blob will be removed from the cache (i.e. a subsequent call to `createBlobForInput` for the same blob id will open a server-side blob).
55
-
** If the transaction associated with the blob is committed or rolled back (when `COMMITTED` or `ROLLED_BACK` is notified), all blobs of that transaction are removed from the cache.
56
-
57
-
=== Pending decisions
58
-
59
-
The following needs to be investigated in more detail before a final decision can be made.
60
-
61
-
* The local blob may need to be able to open a server-side blob for info requests, or explicitly throw an exception for those cases.
62
-
* We may need some checks on the arguments of the BPB and/or `BlobConfig` to ensure it is suitable to return the local blob, or if a server-side blob needs to be opened, check for a subtype (not available in information items), and possibly the charset id requested.
54
+
If the blob cache exceeds the `maxInlineBlobSize`, the inline blob to be registered will be thrown away.
55
+
** Once requested, the blob will be removed from the cache (i.e. a subsequent call to `createBlobForInput` for the same transaction and blob id will open a server-side blob).
56
+
** If the transaction associated with the blob is committed, rolled back or prepared (when `COMMITTED`, `ROLLED_BACK` or `PREPARED` is notified), all blobs of that transaction are removed from the cache.
57
+
* The default value of `maxBlobCacheSize` and `maxInlineBlobSize` can be overridden with system properties `org.firebirdsql.jdbc.defaultMaxBlobCacheSize` and `org.firebirdsql.jdbc.defaultMaxInlineBlobSize`
58
+
* The information request on an inline blob (pure Java) will filter the information request (this is similar to the native implementation)
59
+
** If a requested information item is unknown (i.e. not in the information items sent in `op_inline_blob`), no exception is thrown, and the filtered information response will not include it.
60
+
* On opening a blob that should use the "`default`" settings, Jaybird will no longer provide a parameter buffer or `BlobConfig`.
63
61
+
64
-
For example, currently Jaybird will set `isc_bpb_source_type` and `isc_bpb_target_type` to the subtype of the field, and for subtype `TEXT` `isc_bpb_target_interp` to the charset id of the field.
65
-
We could assume that if source_type and target_type have the same value, we can use the cached inline blob.
66
-
* Alternative for previous, there needs to be some mechanism so the caller can signal that the cache *should not* be used.
62
+
Rationale: The native implementation will not use the cached inline blob if one is opened with any blob parameter buffer.
67
63
+
68
-
This is probably too complex and will never actually be used.
69
-
* Alternative for previous, there needs to be some mechanism so the caller can signal that the cache *should* be used.
64
+
Unfortunately, this does mean undoing changes introduced in Jaybird 5 to always explicitly provide a DPB on open with `isc_bpb_source_type` and `isc_bpb_target_type` set to the known subtype, and -- for `SUB_TYPE TEXT` -- `isc_bpb_target_interp` set to the charset id of the field.
70
65
+
71
-
This is probably too complex, and would only get used by Jaybird itself.
72
-
** A more
66
+
We will retain a similar solution creating a BPB for create.
73
67
74
68
=== Rejected decisions
75
69
@@ -82,11 +76,18 @@ It also prevents overloading the meaning of `blobBufferSize`.
82
76
* Make `maxBlobCacheSize` set to `0` disable inline blobs as well.
83
77
+
84
78
Having a single property control enabling and disabling inline blobs is simpler.
79
+
* The blob config or blob parameter buffer has an extra option to communicate that the inline blob cache should (or should not) be used.
80
+
+
81
+
Although this would be a viable solution for pure Java, and we initially implemented a Jaybird-specific BPB-item that signalled the inline cache should be bypassed.
82
+
This does not work for the native API, as that will only use an inline blob if no blob parameter buffer is used, and open a remote blob if any blob parameter buffer is provided.
83
+
To maintain a coherent API, we decided to do the same for pure Java.
85
84
86
85
== Consequences
87
86
88
87
A version 19 protocol implementation will be added.
89
-
Inline blobs will be used by default when connecting to Firebird 5.0.3 or higher, but can be disabled by setting `maxInlineBlobSize` to `0`.
88
+
Inline blobs will be used by default when connecting to Firebird 5.0.3 or higher, but can be disabled by setting `maxInlineBlobSize` to `0` and/or `maxBlobCacheSize` to `0`.
89
+
90
+
If only the cache is disabled, the server will still send inline blobs, but the client will immediately discard them.
Copy file name to clipboardExpand all lines: src/docs/asciidoc/release_notes.adoc
+49Lines changed: 49 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -433,6 +433,8 @@ This is especially noticeable in connections with high latency.
433
433
434
434
Artificial testing on local WiFi with small blobs shows around 85% increase in throughput (comparing a 6.0.1-SNAPSHOT against 6.0.0).
435
435
436
+
The <<blob-performance-inline-blob>> for Firebird 5.0.3 and higher replaces this improvement for smallish blobs, but it still has benefit for blobs larger than `maxInlineBlobSize` or blobs that are discarded when the inline blob cache is full.
437
+
436
438
This optimization is available for Firebird 2.1 and higher, but formally only supported for Firebird 3.0 and higher.
437
439
438
440
This optimization was backported to Jaybird 5.0.7 and Jaybird 6.0.1.
@@ -456,6 +458,53 @@ This optimization was backported to Jaybird 5.0.7 and Jaybird 6.0.1.
456
458
457
459
For native connections, a similar optimization is available when using a Firebird 5.0.2 or higher fbclient, independent of the Jaybird version.
458
460
461
+
[#blob-performance-inline-blob]
462
+
==== Inline blob support
463
+
464
+
Introduced in Firebird 5.0.3 (protocol 19), inline blobs offer a significant performance improvement for querying smallish blobs.
465
+
As the name suggests, blobs are sent _inline_ together with the row data, avoiding additional round trips to the server for reading the blob data and blob information.
466
+
467
+
There are two connection properties affecting inline blobs:
Maximum size in bytes of the blob (default: `65535`). +
471
+
A value of `0` will disable sending of inline blobs.
472
+
+
473
+
The maximum value is decided by the Firebird server, and is currently `65535`;
474
+
this may change in the future
475
+
+
476
+
If a blob is smaller than the specified size, the server will send it inline.
477
+
The size includes segment lengths, so the actual maximum blob data received is `_N_ * 2` bytes smaller, where _N_ is the number of segments of the actual blob.
478
+
+
479
+
The default can be changed with system property `org.firebirdsql.jdbc.defaultMaxInlineBlobSize`.
Maximum size in bytes -- per connection -- of the blob cache (default: `10485760` or 10 MiB). +
483
+
A value of `0` will disable the cache, but does not disable sending of inline blobs.
484
+
Set `maxInlineBlobSize` to `0` to disable sending of inline blobs.
485
+
+
486
+
For pure Java, only the data size is counted towards the cache size.
487
+
For native, the segment lengths also count towards the cache size.
488
+
+
489
+
The default can be changed with system property `org.firebirdsql.jdbc.defaultMaxBlobCacheSize`.
490
+
491
+
This feature works with pure Java and native connections when connecting to Firebird 5.0.3 or higher.
492
+
For native connections, a Firebird 5.0.3 or higher client library must be used.
493
+
494
+
If the maximum blob cache size is reached, received inline blobs will be discarded.
495
+
For pure Java connections, an inline blob is removed from the cache on first use, or when the transaction associated with the blob ends.
496
+
The native client implementation may have different cache eviction rules.
497
+
498
+
As pure java connections remove the inline blob from the cache on first use, subsequent attempts to read the same blob -- by getting a different instance of `java.sql.Blob` or through multiple calls to the `ResultSet.getXXX` methods -- will use a server-side blob.
499
+
This can also happen if multiple columns or rows, even in different result sets on the same connection, point to the same blob id in the same transaction.
500
+
501
+
If you execute queries returning blobs, while those blobs are never actually opened, you may fill up the cache and later received inline blobs are then discarded.
502
+
Especially in long-running transactions, this may reduce the effectiveness of this feature.
503
+
504
+
Artificial testing on local WiFi with small blobs (200 bytes) shows a 30,000-45,000% (yes, thousand)footnote:[The wide range of the percentages is due to running the test with a single hop and two hops between client and server, and thus a wide range of latency.] increase in throughput comparing a 6.0.2-SNAPSHOT against 6.0.0, and a 15,000-25,000% increase in throughput comparing a 6.0.2-SNAPSHOT against 6.0.1.
505
+
506
+
This optimization was backported to Jaybird 5.0.8 and Jaybird 6.0.2.
0 commit comments