Large objects let DB2 for z/OS keep documents, images, and other bulky values in SQL tables without stuffing megabytes into every base page. This page covers the three LOB types, auxiliary storage, locators versus real values, host variables and file references, inline LOBs, logging and compression, and how utilities back them up.
A LOB is a varying-length value that can be far larger than VARCHAR or VARGRAPHIC. Maximum length is about 2 GB. You declare a length so Db2 and the application know the ceiling; you do not pay 2 GB per row.
| Type | Stores | Notes |
|---|---|---|
| BLOB(n) | Binary bytes (images, files, encrypted payloads) | No character CCSID semantics |
| CLOB(n) | Large character strings | SBCS or mixed text; n up to ~2 GB |
| DBCLOB(n) | Large double-byte / graphic strings | Inline length is in characters (max 16340 inline) |
1234567CREATE TABLE HR.EMP_DOCS ( EMPNO CHAR(6) NOT NULL, RESUME CLOB(10M), PHOTO BLOB(5M), NOTES DBCLOB(1M), PRIMARY KEY (EMPNO) ) IN APPDB.EMPDOC_TS;
A table may have many LOB columns. Each table that has at least one LOB also needs a ROWID (explicit or implicitly generated). ROWID is how Db2 finds the matching auxiliary row. Do not confuse ROWID with an identity column; it is a separate type for row identity and LOB linkage.
Compared with VARCHAR, use a LOB when the value can grow past ordinary page-size string limits or when you want locator/file-reference access. A 40-byte status code is still CHAR or VARCHAR.
| Piece | Role |
|---|---|
| Base table + LOB column | SQL name the program uses; holds ROWID and optional inline bytes |
| ROWID | Links the base row to the auxiliary LOB value (17-byte varying identifier) |
| LOB table space | Physical space for auxiliary pages; one LOB per page, a LOB may span pages |
| Auxiliary table | Holds one LOB column of the base table (per partition if partitioned) |
| Auxiliary index (LOB index) | Exactly one index on the auxiliary table, used to find the LOB by ROWID linkage |
One page of a LOB table space never holds more than one LOB; one LOB may span many pages. An auxiliary table stores one LOB column of the base table. If the base table space is partitioned and you have two LOB columns and ten partitions, you are looking at twenty LOB table spaces, twenty auxiliary tables, and twenty auxiliary indexes. That arithmetic is why shops care about implicit creation and about not adding LOB columns casually to a 1000-partition table.
On modern universal table spaces, defining the LOB column is often enough: Db2 implicitly creates the LOB table space, auxiliary table, and auxiliary index in the same database as the base table. You CREATE AUXILIARY TABLE and CREATE LOB TABLESPACE explicitly when the layout requires it (classic partitioned cases). The auxiliary CREATE does not list user columns the way CREATE TABLE does; you name the base table and LOB column and Db2 builds the structure. The auxiliary index is the same: you name the auxiliary table; Db2 generates the key.
Inline LOBs do not remove this requirement. Even if every value fits in the base row, the auxiliary objects must exist or the table definition is incomplete and INSERT fails.
INLINE LENGTH stores a prefix of the LOB in the base table space with the other columns.
Valid INLINE LENGTH: 0–32680 bytes for BLOB and CLOB, 0–16340 characters for DBCLOB. Subsystem parameter LOB_INLINE_LENGTH (0–32680, default 0) sets the default for new LOB columns in universal table spaces. You can also specify INLINE LENGTH on CREATE TABLE or ALTER TABLE ADD.
1234CREATE TABLE HR.EMP_DOCS ( EMPNO CHAR(6) NOT NULL, RESUME CLOB(10M) INLINE LENGTH 200 ) IN APPDB.EMPDOC_TS;
A resume whose first 200 bytes are what the list screen shows is a classic inline win: the list query stays on the base pages; the interview program fetches the rest.
An actual LOB value is the bytes (or characters) themselves, in a host variable, a file, or the table. A locator is a small token that refers to a LOB value the Db2 server is currently holding. The program does not own the 10 MB string; it owns a 4-byte handle.
| Statement | Effect |
|---|---|
| FETCH/SELECT into a locator host variable | Server holds the LOB; program receives a 4-byte token |
| FREE LOCATOR :hv | Release the server-side value as soon as you are done |
| HOLD LOCATOR :hv | Keep the locator across COMMIT (still freed by FREE LOCATOR or rollback of a later UOW rules) |
| COMMIT / ROLLBACK without HOLD | Locator association ends with the unit of work |
1234567891011EXEC SQL SELECT RESUME INTO :RESUME-LOC FROM HR.EMP_DOCS WHERE EMPNO = :EMPNO END-EXEC. EXEC SQL SET :RESUME-LEN = LENGTH(:RESUME-LOC) END-EXEC. EXEC SQL FREE LOCATOR :RESUME-LOC END-EXEC.
In COBOL, declare locators with USAGE IS SQL TYPE IS CLOB-LOCATOR, BLOB-LOCATOR, or DBCLOB-LOCATOR (PL/I uses CLOB_LOCATOR and friends). FETCH or SELECT INTO the locator assigns the token. You can pass the locator into SUBSTR, POSSTR, LENGTH, INSERT, or UPDATE so the server copies or slices without shipping the whole object to the address space.
Locators belong to the transaction. COMMIT or ROLLBACK drops them unless you issued HOLD LOCATOR. FREE LOCATOR releases one or more locators early — do that in loops so the server does not accumulate held LOBs until commit. HOLD is for the case where you COMMIT but must keep talking about the same LOB in the next unit of work.
Three application representations:
File references are how you INSERT a document from USS or a data set without a giant working storage field, and how you SELECT a CLOB out to a file. LOAD and UNLOAD also use file reference variables in SYSREC when each LOB value lives in its own file (PDS/PDSE member or HFS). Db2 10 added SPANNED / RECFM=VBS so LOBs can ride in the SYSREC data set itself instead of sidecar files.
INSERT supplies a host variable, a locator, a file reference, or a LOB expression (SUBSTR of another LOB, a string cast to CLOB, and so on). UPDATE replaces the whole LOB or a piece via OVERLAY / SET col = SUBSTR(…) CONCAT new-piece CONCAT …. There is no “byte 5000 of this CLOB is now X” row-store operation independent of those expressions; you build a new value.
Retrieval: SELECT the column into a host variable (materialize), into a locator (handle), or into a file reference (write a file). Streaming means: take a locator, loop SUBSTR with a sliding offset, process a chunk, FREE when done. That pattern keeps virtual storage flat and is the usual advice for COBOL and stored procedures that must not allocate 2 GB.
Never SELECT a LOB column in a list screen “just in case.” Each fetch may drag auxiliary pages. Project the LOB only on the detail path, or project LENGTH and an inline prefix.
| Function | Use |
|---|---|
| LENGTH / OCTET_LENGTH | Size of the LOB without fetching the payload |
| SUBSTR | Take a piece; often used with a locator |
| POSSTR | Find a substring position in a CLOB/DBCLOB |
| CONCAT / || | Concatenate LOB or LOB and string (watch result size) |
| OVERLAY | Replace a slice of a LOB value |
These functions accept locators. LENGTH(:locator) is the standard way to learn size before you decide whether to materialize. CAST between CLOB and VARCHAR is possible within limits; do not CAST a 10 MB CLOB to VARCHAR(32704) and hope.
A LOB table space can be defined with LOG YES or LOG NO. LOG YES logs LOB data changes (still expensive at 2 GB). LOG NO skips logging the LOB payload (system pages are another matter): recovery then depends on image copies, and some operations leave the space in a recover-pending type of state if you do not copy. Match LOG on the LOB space to your recovery contract. Inline bytes live in the base table space and follow the base space’s logging.
Compression: LOB table spaces can use compression (including zEDC-related options on supported levels). Compressing huge text CLOBs often pays; compressing already-compressed JPEG BLOBs often does not. COMPRESS on the base table space does not compress the auxiliary LOB pages.
Performance checklist:
Treat the base table space and its LOB table spaces as one recovery set. COPY both. RECOVER both to the same point. A point-in-time recover of only the base leaves auxiliary data from a different time — CHECK-pending and broken documents.
RUNSTATS on base plus LOB spaces keeps the optimizer honest about auxiliary I/O. Skipping LOB stats is a common reason a “simple” SELECT of a CLOB looks cheap in your head and expensive on the accounting report.
A normal column is a sticky note on the page of a notebook. A LOB is a poster that will not fit on the page, so Db2 puts a ticket stub (ROWID) on the page and hangs the poster in a warehouse (LOB table space). Inline LOB means taping the first few inches of the poster onto the notebook page so you can read the title without walking to the warehouse. A locator is not the poster; it is a coat-check token. FREE LOCATOR gives the token back. HOLD LOCATOR lets you keep the token even after you take a break (COMMIT). CHECK LOB is walking the warehouse to see whether any posters are torn.
1. Which type stores large binary values such as images?
2. Where does most LOB data live?
3. What is a LOB locator?
4. What does INLINE LENGTH do?
5. What does CHECK LOB do?