oracle之 Oracle LOB 详解

时间:2022-03-09 10:56:50

一.  官方说明

Oracle 11gR2 文档:

LOB Storage

http://download.oracle.com/docs/cd/E11882_01/appdev.112/e18294/adlob_tables.htm#ADLOB45267

Oracle 10gR2 文档:

LOBs in Tables

http://download.oracle.com/docs/cd/B19306_01/appdev.102/b14249/adlob_tables.htm#sthref165

1.1 Creating Tables That Contain LOBs

When creating tables that contain LOBs, use the guidelines described in the followingsections:

1.1.1 Initializing Persistent LOBs to NULL or Empty

You can set apersistent LOB — ­that is, a LOB column in a table, or a LOB attribute in anobject type that you defined— to be NULL or empty:

(1)Settinga Persistent LOB to NULL: A LOB setto NULL has no locator. A NULL value is stored in the rowin the table, not a locator. This is the same process as for all other datatypes.

(2)Settinga Persistent LOB to Empty: By contrast, an empty LOBstored in a table is a LOB of zero length that has a locator. So, ifyou SELECT from an empty LOB column or attribute, then you get back alocator which you can use to populate the LOB with data using supported programmaticenvironments, such as OCI or PL/SQL(DBMS_LOB).

--NULL 与 Empty的区别是NULL 没有locator指针,而Empty 有locator 指针。

1.1.2 Setting a Persistent LOB to NULL

You may want toset a persistent LOB value to NULL upon inserting the row in caseswhere you do not have the LOB data at the time of the INSERT or ifyou want to use a SELECT statement, such as the following, to determinewhether the LOB holds a NULL value:

SELECT COUNT (*) FROM print_media WHERE ad_graphic IS NOT NULL;

SELECT COUNT (*) FROM print_media WHERE ad_graphic IS NULL;

Note that you cannot call OCI or DBMS_LOB functions on a NULL LOB, so you mustthen use an SQL UPDATE statement to reset the LOB column to anon-NULL (or empty) value.

--如果想使用OCI 或者DBMS_LOB, LOB 列需要设置为非NULL 或者empty。

The point isthat you cannot make a function call from the supported programmaticenvironments on a LOB that is NULL. These functions only work with alocator, and if the LOB column is NULL, then there is no locator in therow.

1.1.3 Settinga Persistent LOB to Empty

You can initialize a persistent LOB to EMPTY rather that NULL. Doing so,enables you to obtain a locator for the LOB instance without populating the LOBwith data.

To set apersistent LOB to EMPTY, use the SQLfunction EMPTY_BLOB() or EMPTY_CLOB() inthe INSERT statement:

SQL>INSERTINTO a_table VALUES (EMPTY_BLOB());

As an alternative, you can use the RETURNING clause to obtain the LOBlocator in one operation rather than calling a subsequent SELECT statement:

  1. DECLARE
  2. Lob_loc  BLOB;
  3. BEGIN
  4. INSERT INTO a_table VALUES (EMPTY_BLOB()) RETURNING blob_col INTO Lob_loc;
  5. /*Now use the locator Lob_loc to populate the BLOB with data */
  6. END;

1.1.4 Initializing LOBs

You can initialize the LOBs in print_media by using thefollowing INSERT statement:

SQL>INSERTINTO print_media VALUES (1001, EMPTY_CLOB(), EMPTY_CLOB(), NULL,EMPTY_BLOB(),EMPTY_BLOB(), NULL, NULL, NULL, NULL);

This sets thevalueof ad_sourcetext, ad_fltextn, ad_composite, and ad_photo toan empty value, and sets ad_graphic to NULL.

1.1.5 Initializing Persistent LOB Columns and Attributes to a Value

You caninitialize the LOB column or LOB attributes to a value that contains more than4G bytes of data, the limit before release 10.2.

--在Oracle 11g中初始化LOB 的内容可以超过4G,而在oracle10g里最大是4G。

A LOB can be up to 8 terabytes or more insize depending on your block size.

A LOB can be up to 128 terabytes or more insize depending on your block size.

这个是初始化的最大值,LOB可存放的最大容量:

Oracle 9iR2 是4G。

Oracle 10g 最大8T。

Oracle 11g 最大是128T。

具体取决与blocksize 的大小。

1.1.6 Initializing BFILEs to NULL or a File Name

A BFILE canbe initialized to NULL or to a filename. To do so, you can usethe BFILENAME() function.

See Also:

"BFILENAMEand Initialization".

1.1.7 Restrictionon First Extent of a LOB Segment

The first extent of any segment requires at least 2 blocks (if FREELISTGROUPS was 0). That is, the initial extent size of the segment should beat least 2 blocks. LOBs segments are different because they need at least 3 blocks in the first extent. If you try tocreate a LOB segment in a permanent dictionary managed tablespace with initial= 2 blocks, then it still works because it is possible for segments in permanent dictionary-managed tablespaces to override the default storagesetting of the tablespaces.

But if uniformlocally managed tablespaces or dictionary managed tablespaces of the temporarytype, or locally managed temporary tablespaces have an extent size of 2 blocks,then LOB segments cannot be created in these tablespaces. This is because inthese tablespace types, extent sizes are fixed and the default storage settingof the tablespaces is not ignored.

1.2 Choosinga LOB Column Data Type

1.2.1 LOBs Compared to LONG and LONG RAW Types

Table11-1 lists the similarities and differences between LOBs, LONGs, andLONG RAW types.

Table 11-1 LOBs Vs. LONG RAW

LOB Data Type

LONG and LONG RAW Data Type

You can store multiple LOBs in a single row

You can store only one LONG or LONG RAW in each row.

LOBs can be attributes of a user-defined data type

This is not possible with either a LONG or LONG RAW

Only the LOB locator is stored in the table column; BLOB and CLOB data can be stored in separate tablespaces and BFILE data is stored as an external file.

For inline LOBs, the database stores LOBs that are less than approximately 4000 bytes of data in the table column.

In the case of a LONG or LONG RAW the entire value is stored in the table column.

When you access a LOB column, you can choose to fetch the locator or the data.

When you access a LONG or LONG RAW, the entire value is returned.

A LOB can be up to 128 terabytes or more in size depending on your block size.

A LONG or LONG RAW instance is limited to 2 gigabytes in size.

There is greater flexibility in manipulating data in a random, piece-wise manner with LOBs. LOBs can be accessed at random offsets.

Less flexibility in manipulating data in a random, piece-wise manner with LONG or LONG RAW data.LONGs must be accessed from the beginning to the desired location.

You can replicate LOBs in both local and distributed environments.

Replication in both local and distributed environments is not possible with a LONG or LONGRAW (see Oracle Database Advanced Replication)

1.2.2 Storing Varying-Width Character Data in LOBs

Varying-width character data in CLOB and NCLOB data types is stored in aninternal format that is compatible with UCS2 Unicode character set format. Thisensures that there is no storage loss of character data in a varying-widthformat. Also note the following if you are using LOBs to store varying-widthcharacter data:

(1)You can create tables containing CLOB and NCLOB columns even if youuse a varying-width CHAR or NCHAR database character set.

(2)You can create a table containing a data type that has a CLOB attributeregardless of whether you use a varying-width CHAR database characterset.

1.2.3 Implicit Character Set Conversions with LOBs

For CLOB and NCLOB instancesused in OCI (Oracle Call Interface), or any of the programmatic environmentsthat access OCI functionality, character set conversions are implicitly performed when translating from one character set to another.

The DBMS_LOB.LOADCLOBFROMFILE API, performs an implicit conversion from binary data to character datawhen loading to a CLOB or NCLOB. With the exception of DBMS_LOB.LOADCLOBFROMFILE,LOB APIs do not perform implicit conversions from binary data to characterdata.

For example,when you use the DBMS_LOB.LOADFROMFILE API to populatea CLOB or NCLOB, you are populating the LOB with binary datafrom a BFILE. In this case, you must perform character set conversions onthe BFILE data before calling DBMS_LOB.LOADFROMFILE.

Note:

The databasecharacter set cannot be changed from a single-byte to a multibyte character setif there are populated user-defined CLOB columns in the database tables.The national character set cannot be changedbetween AL16UTF16 and UTF8 if there are populateduser-defined NCLOB columns in the database tables.

1.3 LOB Storage Parameters

1.3.1 Inlineand Out-of-Line LOB Storage

LOB columnsstore locators that reference the location of the actual LOB value. Dependingon the column properties you specify when you create the table, and dependingthe size of the LOB, actual LOB values are stored either in the table row(inline) or outside of the table row (out-of-line).

LOB 存储分为2种: Inline 和 Out-Of-Line Storage。 Inline Storage 是存储在表的空间里,而out-of-line storage 是存储在lobsegment里的。

LOB values are stored out-of-line when any of the following situations apply:

(1)If youexplicitly specify DISABLE STORAGE IN ROW forthe LOB storage clause when you create the table.

(2)If the sizeof the LOB is greater than approximately 4000 bytes(4000 minus system control information), regardless of the LOB storageproperties for the column.

(3)If you updatea LOB that is stored out-of-line and the resulting LOB is less thanapproximately 4000 bytes, it is still stored out-of-line.

LOB values are stored inline when any of the following conditions apply:

(1)When the sizeof the LOB stored in the given row is small, approximately 4000 bytes or less,and you either explicitly specify ENABLE STORAGE IN ROW orthe LOB storage clause when you create the table, or when you do not specifythis parameter (which is the default).

(2)When the LOB value is NULL (regardless of the LOB storageproperties for the column).

Using the default LOB storage properties (inline storage) canallow for better database performance; it avoids theoverhead of creating and managing out-of-line storage for smaller LOB values.If LOB values stored in your database are frequently small in size, then usinginline storage is recommended.

Note:

(1)LOB locatorsare always stored in the row.

(2)A LOB locatoralways exists for any LOB instance regardless of the LOB storage properties orLOB value - NULL, empty, or otherwise.

(3)If the LOB iscreated with DISABLE STORAGE IN ROW properties and the Basic FilesLOB holds any data, then a minimum of one CHUNK of out-of-line storagespace is used; even when the size of the LOB is less thanthe CHUNK size.

(4)If a LOBcolumn is initialized with EMPTY_CLOB() or EMPTY_BLOB(), then noLOB value exists, not even NULL. The row holds a LOB locator only. Noadditional LOB storage is used.

(5)LOB storageproperties do not affect BFILE columns. BFILE data is always stored in operating system files outside the database.

1.3.2 Defining Tablespaceand Storage Characteristics for Persistent LOBs

When defining LOBs in a table, you can explicitly indicate the tablespace and storagecharacteristics for each persistent LOB column.

To create aBasicFiles LOB, the BASICFILE keyword is optional but is recommendedfor clarity, as shown in the following example:

  1. CREATE TABLE ContainsLOB_tab (n NUMBER, c CLOB)
  2. lob (c) STORE AS BASICFILE segname (TABLESPACE lobtbs1 CHUNK 4096
  3. PCTVERSION 5
  4. NOCACHE LOGGING
  5. STORAGE (MAXEXTENTS 5)
  6. );

For SecureFiless, the SECUREFILE keyword is necessary, as shown in thefollowing example (assuming TABLESPACE lobtbs1 is ASSM):

  1. CREATE TABLE ContainsLOB_tab1 (n NUMBER, c CLOB)
  2. lob (c) STORE AS SECUREFILE sfsegname (TABLESPACE lobtbs1
  3. RETENTION AUTO
  4. CACHE LOGGING
  5. STORAGE (MAXEXTENTS 5)
  6. );

 Note:

There are notablespace or storage characteristics that you can specifyfor external LOBs (BFILEs) as they are not stored in the database.

If you must modify the LOB storage parameters on an existing LOB column, then usethe ALTER TABLE ... MOVE statement. You can changethe RETENTION, PCTVERSION,CACHE, NOCACHE LOGGING, NOLOGGING,or STORAGE settings. You can also changethe TABLESPACE using the ALTER TABLE ... MOVE statement.

1.3.3 Assigninga LOB Data Segment Name

As shown in the previous example, specifying a name for the LOB data segment makes for a muchmore intuitive working environment. When querying the LOB data dictionary views USER_LOBS, ALL_LOBS, DBA_LOBS (see OracleDatabase Reference), you see the LOB data segment that you chose instead ofsystem-generated names.

1.3.4 LOB Storage Characteristics for LOB Column or Attribute

LOB storage characteristics that can be specified for a LOB column or a LOB attributeinclude the following:

(1)TABLESPACE

(2)PCTVERSION or RETENTION

(3)CACHE/NOCACHE/CACHE READS

(4)LOGGING/NOLOGGING

(5)CHUNK

(6)ENABLE/DISABLE STORAGE IN ROW

(7)STORAGE

Note that you can specify either PCTVERSION or RETENTION for BasicFilesLOBs, but not both. For SecureFiless, only the RETENTION parametercan be specified.

For most users, defaults for these storagecharacteristics are sufficient. If you want to fine-tune LOB storage, thenconsider the following guidelines.

1.3.4.1 TABLESPACE and LOB Index

Best performancefor LOBs can be achieved by specifying storage for LOBs in a tablespacedifferent from the one used for the table that contains the LOB. If manydifferent LOBs are accessed frequently, then it may also be useful to specify aseparate tablespace for each LOB column or attribute in order to reduce devicecontention.

The LOB index isan internal structure that is strongly associated with LOB storage. This implies that a user may not drop the LOB index and rebuild it.

--LOB index 是随Lobsegment 自动创建的,不能只删除和重建LOB index。

Note:

The LOB index cannot be altered. –LOB index 不能被修改。

The system determines which tablespace to use for LOB data and LOB index depending on yourspecification in the LOB storage clause:

(1)If youdo not specify a tablespace for the LOB data, then the tablespace ofthe table is used for the LOB data and index.

(2)If youspecify a tablespace for the LOB data, then both the LOB data and index use thetablespace that was specified.

--lobsegment 和lobindex 使用相同的表空间

1.3.4.2 Tablespace for LOB Index in Non-Partitioned Table

When creating atable, if you specify a tablespace for the LOB index for a non-partitionedtable, then your specification of the tablespace is ignored and the LOB indexis co-located with the LOB data. Partitioned LOBs do not include the LOB indexsyntax.

Specifying aseparate tablespace for the LOB storage segments enables a decrease incontention on the tablespace of the table.

1.3.4.3 PCTVERSION

When a BasicFiles LOB is modified, a new version of the BasicFiles LOB page isproduced in order to support consistent read of prior versions of theBasicFiles LOB value.

PCTVERSION is the percentage of all used BasicFiles LOB data space that can be occupied byold versions of BasicFiles LOB data pages. As soon as old versions ofBasicFiles LOB data pages start to occupy more thanthe PCTVERSION amount of used BasicFiles LOB space, Oracle Databasetries to reclaim the old versions and reuse them. In other words, PCTVERSION isthe percent of used BasicFiles LOB data blocks that is available for versioningold BasicFiles LOB data.

Oracle 的一致性通过UNDO 来体现,而LOB 的一致性是例外,是通过自己来实现的,就是在修改之前先copy 一下对应的chunk,chunk 是LOB的基本单位。 这个PCTVERSION就是一个用来控制回滚空间大小的一个参数,该值越大,回滚的时间相对就长,但是占用的空间也就越大。

PCTVERSION has a default of 10 (%), a minimum of 0, and amaximum of 100.

To decide whatvalue PCTVERSION should be set to, consider the following:

(1)How oftenBasicFiles LOBs are updated?

(2)How often theupdated BasicFiles LOBs are read?

Table 11-2 Recommended PCTVERSION Settings

BasicFiles LOB Update Pattern

BasicFiles LOB Read Pattern

PCTVERSION

Updates X% of LOB data

Reads updated LOBs

X%

Updates X% of LOB data

Reads LOBs but not the updated LOBs

0%

Updates X% of LOB data

Reads both updated and non-updated LOBs

2X%

Never updates LOB

Reads LOBs

0%

If yourapplication requires several BasicFiles LOB updates concurrent with heavy readsof BasicFiles LOB columns, then consider using a higher valuefor PCTVERSION, such as 20%.

Setting PCTVERSION totwice the default value allows more free pages to be used for old versions ofdata pages. Because large queries may require consistent reads of BasicFilesLOB columns, it may be useful to retain old versions of BasicFiles LOB pages.In this case, BasicFiles LOB storage may grow because the database does notreuse free pages aggressively.

If persistentBasicFiles LOB instances in your application are created and written just onceand are primarily read-only afterward, then updates are infrequent. In thiscase, consider using a lower value for PCTVERSION, such as 5% or lower.

The moreinfrequent and smaller the BasicFiles LOB updates are, the less space must bereserved for old copies of BasicFiles LOB data. If existing BasicFiles LOBs areknown to be read-only, then you could safely set PCTVERSION to 0%because there would never be any pages needed for old versions of data.

当pctversion=0的时候,表示旧版本数据是可以被其他事务产生的版本占用。如果设置为100,就表示旧版本数据永远都不会被覆写使用。

  1. SQL> alter table t move lob(cl) store ast_segment (pctversion 10 disable storage in row);
  2. Table altered
  3. SQL> select table_name, column_name,pctversion, retention, in_row from user_lobs;
  4. TABLE_NAME COLUMN_NAMPCTVERSION RETENTION IN_ROW
  5. ---------- ---------- ---------- ----------------
  6. T         CL                10           NO

1.3.4.4 RETENTION Parameter for BasicFiles LOBs

As an alternative to the PCTVERSION parameter, you can specifythe RETENTION parameter in the LOB storage clause of the CREATETABLE or ALTER TABLE statement. Doing so, configures the LOBcolumn to store old versions of LOB data for a period of time, rather thanusing a percentage of the table space. For example:

  1. CREATE TABLE ContainsLOB_tab (n NUMBER, c CLOB)
  2. lob (c) STORE AS BASICFILE segname (TABLESPACE lobtbs1 CHUNK 4096
  3. RETENTION
  4. NOCACHE LOGGING
  5. STORAGE (MAXEXTENTS 5)
  6. );
	The RETENTION parameter is designed for use with UNDO features of the database, such asFlashback Versions Query. When a LOB column has the RETENTION property set, old versions of the LOB data are retainedfor the amount of time specified by the UNDO_RETENTION parameter.

Note the following withrespect to the RETENTION parameter:

(1)UNDO SQLis not enabled for LOB columns as it is with other data types. You must setthe RETENTION property on a LOB column to use Undo SQL on LOB data.

(2)You cannotset the value of the RETENTION parameter explicitly. The amount oftime for retention of LOB versions in determined bythe UNDO_RETENTION parameter.

--RETENTION 参数不能显示的设置,只能通过UNDO_RETENTION 参数来继承。

(3)Usage ofthe RETENTION parameter is only supported in Automatic UndoManagement mode. You must configure your table for use with Automatic UndoManagement before you can set RETENTION on a LOB column. ASSM is required forLOB RETENTION to be in effect for BasicFiles LOBs.The RETENTION parameter of the SQL (in theSTORE AS clause)is silently ignored if the BasicFiles LOB resides in an MSSM tablespace.

(4)The LOBstorage clause can specify RETENTION or PCTVERSION, but notboth.

--RETENTION 和 PCTVERSION 只能设置一个。

1.3.4.5 RETENTION Parameter for SecureFiless

With 11.1 and above it is recommended to use Securefile instead of basicfiles for the LOBs. The securefiles were developed so that it will anticipate the need to move the HW mark specially with the create, insert, update of the LOBs.

Specifying the RETENTION parameter for SecureFiless indicates that the databasemanages consistent read data for the SecureFiles storage dynamically, takinginto account factors such as the UNDO mode of the database.

(1)Specify MAX if the database is in FLASHBACK mode to limit the size of theLOB UNDO retention in bytes. If you specify MAX, then you mustalso specify the MAXSIZE clause in the storage_clause.

(2)Specify MIN if the database is in FLASHBACK mode to limitthe UNDO retention duration for the specific LOB segmentto n seconds.

(3)Specify AUTO ifyou want to retain UNDO sufficient for consistent read purposes only.This is the default.

(4)Specify NONE ifno UNDO is required for either consistent read or flashback purposes.

The default RETENTION for SecureFilessis AUTO.

1.3.4.6  CACHE / NOCACHE / CACHE READS

Table 11-3 When to Use CACHE, NOCACHE, andCACHE READS

Cache Mode

Read

Write

CACHE READS

Frequently

Once or occasionally

CACHE

Frequently

Frequently

NOCACHE (default)

Once or occasionally

Never

1.3.4.7 CACHE / NOCACHE / CACHE READS: LOB Valuesand Buffer Cache

(1)CACHE: Oracleplaces LOB pages in the buffer cache for faster access.

(2)NOCACHE: As aparameter in the STORE AS clause, NOCACHE specifies thatLOB values are not brought into the buffer cache.

(3)CACHE READS:LOB values are brought into the buffer cache only during read and not duringwrite operations.

NOCACHE is thedefault for both SecureFiless and BasicFiles LOBs.

Note:

Using the CACHE option results in improved performance when reading andwriting data from the LOB column. However, it can potentially age other non-LOBpages out of the buffer cache prematurely.

1.3.4.8 LOGGING / NOLOGGING Parameter for BasicFiles LOBs

[NO]LOGGING hasa similar application with regard to using LOBs as it does for other tableoperations. In the usual case, if the [NO]LOGGING clause is omitted, thenthis means that neither NOLOGGING nor LOGGING is specifiedand the logging attribute of the table or table partition defaults to thelogging attribute of the tablespace in which it resides.

For LOBs, there is afurther alternative depending on how CACHE is stipulated.

(1)CACHE isspecified and [NO]LOGGING clause is omitted. LOGGING isautomatically implemented (because you cannot have CACHE NOLOGGING).

(2)CACHE isnot specified and [NO]LOGGING clause is omitted. The process defaultsin the same way as it does for tables and partitioned tables. That is, the[NO]LOGGINGvalue is obtained from the tablespace in which the LOB segmentresides.

当Lob数据设置为cache的时候,自动就是logging属性。如果设置为nologging,只是lobsegment部分的数据变化不会写redo log,不会影响到其他的in row和column列的数据redo记录工作。

The following issues should also be kept inmind.

(1)LOBs Always Generate Undo for LOB Index Pages

Regardless ofwhether LOGGING or NOLOGGING is set, LOBs never generaterollback information (undo) for LOB data pages because old LOB data is storedin versions. Rollback information that is created for LOBs tends to be smallbecause it is only for the LOB index page changes.

(2)When LOGGING is Set Oracle Generates Full Redo for LOB Data Pages

NOLOGGING isintended to be used when a customer does not care about media recovery. Thus,if the disk/tape/storage media fails, then you cannot recover your changes fromthe log because the changes were never logged.

(3)NOLOGGING is Useful for Bulk Loads or Inserts.

For instance,when loading data into the LOB, if you do not care about redo and can juststart the load over if it fails, set the LOB data segment storagecharacteristics toNOCACHE NOLOGGING. This provides good performance forthe initial load of data.

Once you havecompleted loading data, if necessary, use ALTER TABLE to modifythe LOB storage characteristics for the LOB data segment for normal LOBoperations, for example, to CACHE or NOCACHE LOGGING.

Note:

CACHE implies that you also get LOGGING.

1.3.4.9 LOGGING/FILESYSTEM_LIKE_LOGGING forSecureFiless

NOLOGGING or LOGGING hasa similar application with regard to using SecureFilessas LOGGING/NOLOGGING does for other table operations. In the usualcase, if the logging_clause is omitted, then the SecureFiles inherits itslogging attribute from the tablespace in which it resides. In this case,if NOLOGGING is the default value, the SecureFiles defaultsto FILESYSTEM_LIKE_LOGGING.

Note:

Usingthe CACHE option results in improved performance when reading andwriting data from the LOB column. However, it can potentially age other non-LOBpages out of the buffer cache prematurely.

1.3.4.10 CACHE Implies LOGGING

For SecureFiless, there is a furtheralternative depending on how CACHE is specified:

(1)CACHE isspecified and the LOGGING clause is omitted,then LOGGING is used.

(2)CACHE isnot specified and the logging_clause is omitted. Then the process defaults inthe same way as it does for tables and partitioned tables. That is,the LOGGING value is obtained from the tablespace in which the LOBvalue resides. If the tablespace is NOLOGGING, then the SecureFilesdefaults to FILESYSTEM_LIKE_LOGGING.

The following issues should also be kept in mind.

(1)SecureFilessand an Efficient Method of Generating REDO and UNDO

This means thatOracle Database determines if it is more efficient togenerate REDO and UNDO for the change to a block, similarto heap blocks, or if it generates a version and full REDO of the newblock similar to BasicFiles LOBs.

(2)FILESYSTEM_LIKE_LOGGINGis Useful for Bulk Loads or Inserts

For instance,when loading data into the LOB, if you do not care about REDO and canjust start the load over if it fails, set the LOB data segment storagecharacteristics to FILESYSTEM_LIKE_LOGGING. This provides good performance forthe initial load of data.

Once you havecompleted loading data, if necessary, use ALTER TABLE to modifythe LOB storage characteristics for the LOB data segment for normal LOBoperations. For example, to CACHE or NOCACHE LOGGING.

1.3.4.11 CHUNK

A chunk is one or more Oracle blocks. You can specify the chunk size for the BasicFiles LOBwhen creating the table that contains the LOB. This corresponds to the datasize used by Oracle Database when accessing or modifying the LOB value. Part ofthe chunk is used to store system-related information and the rest stores theLOB value. The API you are using has a function that returns the amount ofspace used in the LOB chunk to store the LOB value. In PL/SQLuse DBMS_LOB.GETCHUNKSIZE. In OCI, useOCILobGetChunkSize().

Note:

If the tablespace block size is the same as the database block size,then CHUNK is also a multiple of the database block size. The default CHUNK size is equal to the size of onetablespace block, and the maximum value is 32K.

--chunk 默认和tablespace 的block 相等,并且最大值为32k。

(1)Choosing the Value of CHUNK

Once the valueof CHUNK is chosen (when the LOB column is created), it cannot bechanged. Hence, it is important that you choose a value which optimizes yourstorage and performance requirements. For SecureFiless CHUNK is anadvisory size and is provided for backward compatibility purposes.

Space Considerations

The valueof CHUNK does not matter for LOBs that are stored inline. Thishappens when ENABLE STORAGE IN ROW is set, and thesize of the LOB locator and the LOB data is less than approximately 4000 bytes.However, when the LOB data is stored out-of-line, it always takes up space inmultiples of the CHUNK parameter. This can lead to a large waste ofspace if your data is small, but the CHUNK is set to a large number.

Table 11-4 Data Size and CHUNK Size

Data Size

CHUNK Size

Disk Space Used to Store the LOB

Space Utilization (Percent)

3500 enable storage in row

irrelevant

3500 in row

100

3500 disable storage in row

32 KB

32 KB

10

3500 disable storage in row

4 KB

4 KB

90

33 KB

32 KB

64 KB

51

2 GB +10

32 KB

2 GB + 32 KB

99+

PerformanceConsiderations

Accessing lobs in big chunks is more efficient. You can set CHUNK to the data sizemost frequently accessed or written. For example, if only one block of LOB datais accessed at a time, then set CHUNK to the size of one block. Ifyou have big LOBs, and read or write big amounts of data, then choose a largevalue for CHUNK.

(2)Set INITIAL and NEXT to Larger than CHUNK

If you explicitly specify storage characteristics for the LOB, then make surethat INITIAL and NEXT for the LOB data segment storage areset to a size that is larger than the CHUNK size. For example, if the databaseblock size is 2KB and you specify a CHUNK of 8KB, then make surethat INITIAL and NEXT are bigger than 8KB and preferablyconsiderably bigger (for example, at least 16KB).

Put another way: If you specify a valuefor INITIAL, NEXT, or the LOB CHUNK size, then make surethey are set in the following manner:

CHUNK <= NEXT

CHUNK <= INITIAL

1.3.4.12 ENABLE or DISABLE STORAGE IN ROW Clause

You use the ENABLE | DISABLE STORAGE IN ROW clauseto indicate whether the LOB should be stored inline (in the row) or out-of-line.

Note:

You may notalter this specification once you have made it: if you ENABLE STORAGE INROW, then you cannot alter it to DISABLE STORAGE IN ROW and viceversa.

The defaultis ENABLE STORAGE IN ROW.

Guidelines for ENABLE or DISABLE STORAGE IN ROW

The maximumamount of LOB data stored in the row is the maximum VARCHAR2 size(4000). This includes the control information and the LOB value. If youindicate that the LOB should be stored in the row, once the LOB value andcontrol information is larger than approximately 4000, then the LOB value isautomatically moved out of the row.

This suggests thefollowing guidelines:

The default,ENABLE STORAGE IN ROW, is usually the best choice for the following reasons:

(1)Small LOBs:If the LOB is small (less than approximately 4000 bytes), then the whole LOBcan be read while reading the row without extra disk I/O.

(2)Large LOBs:If the LOB is big (greater than approximately 4000 bytes), then the controlinformation is still stored in the row if ENABLE STORAGE IN ROW is set, evenafter moving the LOB data out of the row. This control information could enableus to read the out-of-line LOB data faster.

However, in somecases DISABLE STORAGE IN ROW is a better choice. This is because storing theLOB in the row increases the size of the row. This impacts performance if youare doing a lot of base table processing, such as full table scans, multi-rowaccesses (range scans), or many UPDATE/SELECT to columns other than the LOBcolumns.

1.4 Indexing LOB Columns

This section discusses different techniquesyou can use to index LOB columns.

Note:

After you move a LOB column any existing table indexes mustbe rebuilt.

1.4.1 Using Domain Indexing on LOB Columns

You might beable to improve the performance of queries by building indexes specificallyattuned to your domain. Extensibility interfaces provided with the databaseallow for domain indexing, a framework for implementing such domain specificindexes.

Note:

You cannot builda B-tree or bitmap index on a LOB column.

1.4.2 Indexing LOB Columns Using a Text Index

Depending on the nature of the contents of the LOB column, one of the Oracle Text options couldalso be used for building indexes. For example, if a text document is stored in a CLOB column, then you can build a text index to speed up the performanceof text-based queries over the CLOB column.

1.4.3 Function-Based Indexes on LOBs

A function-based index is an index builton an expression. It extends your indexing capabilities beyond indexing on acolumn. A function-based index increases the variety of ways in which you canaccess data.

Function-basedindexes cannot be built on nested tables or LOB columns. However, you can buildfunction-based indexes on VARRAYs.

Like extensible indexes and domain indexes on LOB columns,function-based indexes are also automatically updated when a DML operation isperformed on the LOB column. Function-based indexes are also updated when anyextensible index is updated.

1.4.4 ExtensibleIndexing on LOB Columns

The database provides extensible indexing, a feature which enables you to define new index types as required.This is based on the concept of cooperative indexing where a data cartridge and the database build and maintain indexes for data types such as text and spatialfor example, for On-line-Analytical Processing (OLAP).

The cartridge isresponsible for defining the index structure, maintaining the index contentduring load and update operations, and searching the index during queryprocessing. The index structure can be stored in Oracle as heap-organized, oran index-organized table, or externally as an operating system file.

To support this structure, the database providesan indextype. The purpose of an indextype is toenable efficient search and retrieval functions for complex domains such astext, spatial, image, and OLAP by means of a data cartridge. An indextype isanalogous to the sorted or bit-mapped index types that are built-in within theOracle Server. The difference is that an indextype is implemented by the datacartridge developer, whereas the Oracle kernel implements built-in indexes.Once a new indextype has been implemented by a data cartridge developer, endusers of the data cartridge can use it just as they would built-in indextypes.

When thedatabase system handles the physical storage of domain indexes, data cartridges

(1)Define theformat and content of an index. This enables cartridges to define an indexstructure that can accommodate a complex data object.

(2)Build,delete, and update a domain index. The cartridge handles building andmaintaining the index structures. Note that this is a significant departurefrom the medicine indexing features provided for simple SQL data types. Also,because an index is modeled as a collection of tuples, in-place updating isdirectly supported.

(3)Access andinterpret the content of an index. This capability enables the data cartridgeto become an integral component of query processing. That is, thecontent-related clauses for database queries are handled by the data cartridge.

By supportingextensible indexes, the database significantly reduces the effort needed todevelop high-performance solutions that access complex data types such as LOBs.

1.4.5 Extensible Optimizer

The extensible optimizer functionality allows authors of user-defined functions and indexes tocreate statistics collections, selectivity, and cost functions. Thisinformation is used by the optimizer in choosing a query plan. The cost-basedoptimizer is thus extended to use the user-supplied information.

Extensible indexing functionality enables you to define new operators, index types, anddomain indexes. For such user-defined operators and domain indexes, theextensible optimizer functionality allows users to control the three maincomponents used by the optimizer to select an execution plan: statistics,selectivity, and cost.

1.4.6 OracleText Indexing Support for XML

You can createOracle Text indexes on CLOB columns and perform queries on XML data.

1.5 Manipulating LOBs in Partitioned Tables

You canpartition tables that contain LOB columns. As aresult, LOBs can take advantage of all of the benefits of partitioningincluding the following:

(1)LOB segmentscan be spread between several tablespaces to balance I/O load and to makebackup and recovery more manageable.

(2)LOBs in apartitioned table become easier to maintain.

(3)LOBs can bepartitioned into logical groups to speed up operations on LOBs that areaccessed as a group.

This section describes some of the ways you can manipulate LOBs in partitioned tables.

1.5.1 Partitioninga Table Containing LOB Columns

LOBs aresupported in RANGE partitioned, LIST partitioned, and HASH partitioned tables.Composite heap-organized tables can also have LOBs.

You can partition a tablecontaining LOB columns using the following techniques:

(1)When thetable is created using the PARTITION BY ... clause of the CREATETABLE statement.

(2)Adding apartition to an existing table using the ALTER TABLE ... ADDPARTITION clause.

(3)Exchangingpartitions with a table that has partitioned LOB columns using the ALTERTABLE ... EXCHANGE PARTITION clause. Note that EXCHANGEPARTITION can only be used when both tables have the same storageattributes, for example, both tables store LOBs out-of-line.

Creating LOBpartitions at the same time you create the table (in the CREATETABLE statement) is recommended. If you create partitions on a LOB columnwhen the table is created, then the column can hold LOBs stored either inlineor out-of-line LOBs.

After a table iscreated, new LOB partitions can only be created on LOB columns that are storedout-of-line. Also, partition maintenance operations, SPLITPARTITION and MERGE PARTITIONS, only work on LOB columns that storeLOBs out-of-line.

1.5.2 Creatingan Index on a Table Containing Partitioned LOB Columns

To improve the performance of queries, you can create indexes onpartitioned LOB columns. For example:

CREATE INDEX index_name

ONtable_name (LOB_column_1, LOB_column_2, ...) LOCAL;

Note that onlydomain and function-based indexes are supported on LOB columns. Other types ofindexes, such as unique indexes are not supported with LOBs.

1.5.3 Moving Partitions Containing LOBs

You can move a LOB partition into a different tablespace. This isuseful if the tablespace is no longer large enough to hold the partition. To doso, use the ALTER TABLE ... MOVE PARTITION clause. For example:

  1. ALTER TABLE current_table MOVE PARTITION partition_name
  2. TABLESPACE destination_table_space
  3. LOB (column_name) STORE AS (TABLESPACE current_tablespace);

1.5.4 SplittingPartitions Containing LOBs

You can split a partition containing LOBs into two equally sizedpartitions using the ALTER TABLE ... SPLIT PARTITION clause. Doing sopermits you to place one or both new partitions in a new tablespace. Forexample:

  1. ALTER TABLE table_name SPLIT PARTITION partition_name
  2. AT (partition_range_upper_bound)
  3. INTO (PARTITION partition_name,
  4. PARTITION new_partition_name TABLESPACE new_tablespace_name
  5. LOB (column_name) STORE AS (TABLESPACE tablespace_name)
  6. ... ;

1.5.5 Merging Partitions Containing LOBs

You can mergepartitions that contain LOB columns using the ALTER TABLE ... MERGEPARTITIONS clause. This technique is useful for reclaiming unusedpartition space. For example:

  1. ALTER TABLE table_name
  2. MERGE PARTITIONS partition_1, partition_2
  3. INTO PARTITION new_partition TABLESPACE new_tablespace_name
  4. LOB (column_name) store as (TABLESPACE tablespace_name)
  5. ... ;

1.6 LOBs in Index Organized Tables

Index OrganizedTables (IOTs) support internal and external LOB columns. For the most part, SQLDDL, DML, and piece wise operations on LOBs in IOTs produce the same results asthose for normal tables. The only exception is the default semantics of LOBsduring creation. The main differences are:

(1)TablespaceMapping: By default, or unless specified otherwise, theLOB data and index segments are created in the tablespace in which the primarykey index segments of the index organized table are created.

(2)Inlineas Compared to Out-of-Line Storage: By default, allLOBs in an index organized table created without an overflow segment are storedout of line. In other words, if an index organized table is created without anoverflow segment, then the LOBs in this table have their default storageattributes as DISABLE STORAGE IN ROW. If you forcibly tryto specify an ENABLE STORAGE IN ROW clause for suchLOBs, then SQL raises an error.

On the otherhand, if an overflow segment has been specified, then LOBs in index organizedtables exactly mimic their semantics in conventional tables (see "DefiningTablespace and Storage Characteristics for Persistent LOBs").

Exampleof Index Organized Table (IOT) with LOB Columns

  1. CREATE TABLE iotlob_tab (c1 INTEGER PRIMARY KEY, c2 BLOB, c3 CLOB, c4
  2. VARCHAR2(20))
  3. ORGANIZATION INDEX
  4. TABLESPACE iot_ts
  5. PCTFREE 10 PCTUSED 10 INITRANS 1 MAXTRANS 1 STORAGE (INITIAL 4K)
  6. PCTTHRESHOLD 50 INCLUDING c2
  7. OVERFLOW
  8. TABLESPACE ioto_ts
  9. PCTFREE 10 PCTUSED 10 INITRANS 1 MAXTRANS 1 STORAGE (INITIAL 8K) LOB (c2)
  10. STORE AS lobseg (TABLESPACE lob_ts DISABLE STORAGE IN ROW
  11. CHUNK 16384 PCTVERSION 10 CACHE STORAGE (INITIAL 2M)
  12. INDEX lobidx_c1 (TABLESPACE lobidx_ts STORAGE (INITIAL 4K)));

Executing thesestatements results in the creation of an index organizedtable iotlob_tab with the following elements:

(1)A primary key index segment in thetablespace iot_ts,

(2)An overflow data segment intablespace ioto_ts

(3)Columns starting fromcolumn C3 being explicitly stored in the overflow data segment

(4)BLOB (column C2) datasegments in the tablespace lob_ts

(5)BLOB (column C2) indexsegments in the tablespace lobidx_ts

(6)CLOB (column C3) datasegments in the tablespace iot_ts

(7)CLOB (column C3) indexsegments in the tablespace iot_ts

(8)CLOB (column C3) storedin line by virtue of the IOT having an overflow segment

(9)BLOB (column C2)explicitly forced to be stored out of line

Note:

If no overflowhad been specified, then both C2 and C3 would have been stored out of line bydefault.

Other LOBfeatures, such as BFILEs and varying character width LOBs, are alsosupported in index organized tables, and their usage is the same as forconventional tables.

1.7 Restrictions for LOBs in Partitioned Index-OrganizedTables

LOB columns aresupported in range-, list-, and hash-partitioned index-organized tables withthe following restrictions:

(1)Composite partitionedindex-organized tables are not supported.

(2)Relational and object partitionedindex-organized tables (partitioned by range, hash, or list) can hold LOBsstored as follows; however, partition maintenance operations, suchas MOVE, SPLIT, and MERGE are not supported with:

1)VARRAY datatypes stored as LOB data types

2)Abstract datatypes with LOB attributes

3)Nested tableswith LOB types

1.8 Updating LOBs in Nested Tables

To update LOBsin a nested table, you must lock the row containing the LOB explicitly. To doso, you must specify the FOR UPDATE clause in the subquery prior to updatingthe LOB value.

Note thatlocking the row of a parent table does not lock the row of a nested tablecontaining LOB columns.

Note:

Nested tablescontaining LOB columns are the only data structures supported for creatingcollections of LOBs. You cannot create a VARRAY of any LOB data type.

二. LOB 说明

2.1 LOB 分类

LOB大对象主要是用来存储大量数据的数据库字段,在Oracle 9iR2 中LOB的最大容量是4G,Oracle 10g 最大8T,Oracle 11g 最大是128T。具体取决与blocksize 的大小。

Oracle 中支持4 种类型的LOB:

CLOB:字符LOB。这种类型用于存储大量的文本信息,如XML 或者只是纯文本。这个数据类型需要进行字符集转换,也就是说,在获取时,这个字段中的字符会从数据库的字符集转换为客户的字符集,而在修改时会从客户的字符集转换为数据库的字符集。

NCLOB:这是另一种类型的字符LOB。存储在这一列中的数据所采用的字符集是数据库的国家字符集,而不是数据库的默认字符集。

BLOB:二进制LOB。这种类型用于存储大量的二进制信息,如字处理文档,图像和你能想像到的任何其他数据。它不会执行字符集转换。应用向BLOB 中写入什么位和字节,BLOB就会返回什么为和字节。

BFILE:二进制文件LOB。这与其说是一个数据库存储实体,不如说是一个指针。带BFILE列的数据库中存储的只是操作系统中某个文件的一个指针。这个文件在数据库之外维护,根本不是数据库的一部分。BFILE 提供了文件内容的只读访问。

LOB数据类型分类:

1.     按存储数据的类型分:
  (1)字符类型:
       CLOB:存储大量 单字节 字符数据。
       NLOB:存储定宽 多字节 字符数据。
  (2)二进制类型:
        BLOB:存储较大无结构的二进制数据。
  (3)二进制文件类型:
        BFILE:将二进制文件存储在数据库外部的操作系统文件中。存放文件路径。

2.     按存储方式分:
   (1)存储在内部表空间(内部LOB):
       CLOB,NLOB和BLOB
   (2)指向外部操作系统文件(外部LOB):
        BFILE

有关LOB 类型的处理,参考之前整理的Blog:

ORACLE LOB 大对象处理

http://blog.csdn.net/tianlesoftware/article/details/5070981

2.2 内部LOB

先看示例:

SQL>create user anqing identified by anqing;

SQL>grant connect,resource,dba to anqing;

SYS@anqing1(rac1)> conn anqing/anqing;

Connected.

ANQING@anqing1(rac1)> create table tl(idnumber primary key,txt clob);

Table created.

TL 表的创建脚本如下:

  1. SQL>selectdbms_metadata.get_ddl( 'TABLE','TL')fromdual;
  2. /* Formatted on 2011/10/2511:26:26 (QP5 v5.163.1008.3004) */
  3. CREATE TABLE"ANQING"."TL"
  4. (
  5. "ID"    NUMBER,
  6. "TXT"   CLOB,
  7. PRIMARYKEY
  8. ("ID")
  9. USINGINDEXPCTFREE10
  10. INITRANS2
  11. MAXTRANS255
  12. STORAGE(INITIAL65536
  13. NEXT1048576
  14. MINEXTENTS1
  15. MAXEXTENTS2147483645
  16. PCTINCREASE0
  17. FREELISTS 1
  18. FREELISTGROUPS1
  19. BUFFER_POOLDEFAULT)
  20. TABLESPACE"USERS"
  21. ENABLE
  22. )
  23. PCTFREE 10
  24. PCTUSED 40
  25. INITRANS 1
  26. MAXTRANS 255
  27. NOCOMPRESS
  28. LOGGING
  29. STORAGE (INITIAL65536
  30. NEXT 1048576
  31. MINEXTENTS1
  32. MAXEXTENTS2147483645
  33. PCTINCREASE0
  34. FREELISTS1
  35. FREELISTGROUPS1
  36. BUFFER_POOLDEFAULT)
  37. TABLESPACE "USERS"
  38. LOB (
  39. "TXT")
  40. STOREAS
  41. (
  42. TABLESPACE"USERS"
  43. ENABLESTORAGEINROW
  44. CHUNK8192
  45. PCTVERSION10
  46. NOCACHELOGGING
  47. STORAGE(INITIAL65536
  48. NEXT1048576
  49. MINEXTENTS1
  50. MAXEXTENTS2147483645
  51. PCTINCREASE0
  52. FREELISTS1
  53. FREELISTGROUPS1
  54. BUFFER_POOLDEFAULT))
  55. ANQING@anqing1(rac1)> set wrap off;
  56. ANQING@anqing1(rac1)> col segment_namefor a35
  57. ANQING@anqing1(rac1)> selectsegment_name, segment_type from user_segments;
  58. SEGMENT_NAME                        SEGMENT_TYPE
  59. -----------------------------------------------------
  60. SYS_C007307                         INDEX
  61. SYS_IL0000056466C00002$            LOBINDEX
  62. SYS_LOB0000056466C00002$           LOBSEGMENT
  63. TL                                  TABLE

SYS_C007307索引用来支持主键约束,lobindex 和lobsegment是为了支持我们的LOB 列。我们的实际LOB 数据就存储在lobsegment 中( 确实,LOB 数据也有可能存储在表T 中,不过稍后讨论ENABLE STORAGE IN ROW 子句时还会更详细地说明这个内容)。lobindex 用于执行LOB 的导航,来找出其中的某些部分。创建一个LOB 列时,一般来说,存储在行中的这是一个指针(pointer),或LOB 定位器(LOB locator)。我们的应用所获取的就是这个LOB 定位器。

当请求得到LOB 的“12.000~2,000 字节”时,将对lobindex 使用LOB 定位器来找出这些字节存储在哪里,然后再访问lobsegment。可以用lobindex 很容易地找到LOB 的各个部分。由此说来,可以把LOB想成是一种主/明细关系。

LOB 按“块”(chunk)或(piece)来存储,每个片段都可以访问。例如,如果我们使用表来实现一个LOB,可以如下做到这一点:

  1. /* Formatted on 2011/10/2510:51:00 (QP5 v5.163.1008.3004) */
  2. CREATE TABLEparent
  3. (
  4. id      INT PRIMARYKEY,
  5. other   data...
  6. );
  7. CREATE TABLElob
  8. (
  9. id                 REFERENCESparentONDELETECASCADE,
  10. chunk_number   INT,
  11. data           <datatype>(n),
  12. primary key(id,chunk_number)
  13. );

从概念上讲,LOB 的存储与之非常相似,创建这两个表时,在LOB 表的ID.CHUNK_NUMBER上要有一个主键(这对应于Oracle创建的lobindex),而且要有一个LOB 表来存储数据块(对应于lobsegment)。LOB列为我们透明地实现了这种主/明细结构。

为了得到LOB 中的N~M字节,要对表中的指针(LOB 定位器)解除引用,遍历lobindex 结构来找到所需的数据库(chunk), 然后按顺序访问。这使得随机访问LOB 的任何部分都能同样迅速,你可以用同样快的速度得到LOB 的最前面、中间或最后面的部分,因为无需再从头开始遍历LOB。

2.2.1.  LOB 表空间

CREATE TABLE 语句包括以下内容:

LOB(TXT)STOREAS(TABLESPACEUSERS…

这里指定的TABLESPACE 是将存储lobsegment 和lobindex 表空间,这可能与表本身所在的表空间不同。也就是说,保存LOB 数据的表空间可能不同于保存实际表数据的表空间。

为什么考虑为LOB 数据使用另外一个表空间(而不用表数据所在的表空间)呢?注意原因与管理和性能有关。从管理的角度看,LOB 数据类型表示一种规模很大的信息。如果表有数百万行,而每行有一个很大的LOB,那么LOB 就会极为庞大。为LOB 数据单独使用一个表空间有利于备份和恢复以及空间管理,单从这一点考虑,将表与LOB 数据分离就很有意义。例如,你可能希望LOB 数据使用另外一个统一的区段大小,而不是普通表数据所用的区段大小。

另一个原因则出于I/O 性能的考虑。默认情况下,LOB 不在缓冲区缓存中进行缓存(有关内容将在后面再做说明)。因此,默认情况下,对于每个LOB 访问,不论是读还是写,都会带来一个物理I/O(从磁盘直接读,或者向磁盘直接写)。

注意: LOB 可能是内联的(inline),或者存储在表中。在这种情况下,LOB 数据会被缓存,但是这只适用于小于4,000 字节的LOB。我们将在“IN ROW 子句”一节中进一步讨论这种情况。

由于每个访问都是一个物理I/O,所以如果你很清楚在实际中(当用户访问时)有些对象会比大多数其他对象经历更多的物理I/O,那么将这些对象分离到它们自己的磁盘上就很有意义。

需要说明,lobindex 和lobsegment 总是会在同一个表空间中。不能将lobindex 和lobsegment 放在不同的表空间中。在Oralce 的更早版本中,允许为lobindex 和lobsegment 分别放在单独的表空间中,但是从8i Release 3 以后,就不再允许为lobindex 和logsegment 指定不同的表空间。实际上,lobindex的所有存储特征都是从lobsegment 继承的。

2.2.2. IN ROW 子句

CREATE TABLE 语句还包括以下内容:

LOB(TXT)STOREAS(…ENABLE STORAGEINROW…

这控制了LOB 数据是否总与表分开存储(存储在lobsegment 中),或是有时可以与表一同存储,而不用单独放在lobsegment 中。如果设置了ENABLE STORAGE IN ROW,而不是DISABLE STORAGE IN ROW,小LOB(最多4,000 字节)就会像VARCHAR2 一样存储在表本身中。只有当LOB 超过了4,000 字节时,才会“移出”到lobsegment 中。

默认行为是启用行内存储(ENABLE STORAGEIN ROW),而且一般来讲,如果你知道LOB 总是能在表本身中放下,就应该采用这种默认行为。例如,你的应用可能有一个某种类型的DESCRIPTION 字段。这个DESCRIPTION 可以存储0~32KB 的数据(或者可能更多,但大多数情况下都少于或等于32KB)。已知很多描述都很简短,只有几百个字符。如果把它们单独存储,并在每次获取时都通过索引来访问,就会存在很大的开销,你完全可以将它们内联存储,即放在表本身中,这就能避免单独存储的开销。不仅如此,如果LOB还能避免获取LOB 时所需的物理I/O。

一般来说,OUT ROW,即将数据存储在segment里,在这种情况下不会在buffer cache 中进行缓存,这样每次都会产生物理IO. 同时对out row 进行读写操作时,虽然有lobindex的存在,但 DML 操作需要同时维护lobindex和lobsegment。 采用OUT ROW 会增加逻辑IO和物理IO,所以默认启用IN ROW。 对lob 进行缓存,减小IO成本。

2.2.3. CHUNK 子句

CREATE TABLE 语句包括以下内容:

LOB("TXT") STORE AS ( ... CHUNK 8192 ... )

LOB 存储在块(chunk)中,指向LOB 数据的索引会指向各个数据块。块(chunk)是逻辑上连续的一组数据库块(block),这也是LOB 的最小分配单元,而通常数据库的最小分配单元是数据库块。CHUNK 大小必须是Oracle 块大小的整数倍,只有这样才是合法值。

从两个角度看,选择CHUNK 大小时必须当心。首先,每个LOB实例(每个行外存储的LOB 值)会占用至少一个CHUNK。一个CHUNK 有一个LOB 值使用。如果一个表有100 行,而每行有一个包含7KB 数据的LOB,你就会分配100 个CHUNK,如果将CHUNK 大小设置为32KB,就会分配100 个32KB 的CHUNK。如果将CHUNK大小设置为8KB,则(可能)分配100 个8KB 的CHUNK。关键是,一个CHUNK 只能有一个LOB 使用(两个LOB 不会使用同一个CHUNK)。如果选择了一个CHUNK 大小,但不符合你期望的LOB 大小,最后就会浪费大量的空间。例如,如果表中的LOB 平均有7KB,而你使用的CHUNK 大小为32KB,对于每个LOB 实例你都会“浪费”大约25KB 的空间,另一方面,倘若使用8KB 的CHUNK,就能使浪费减至最少。

还需要注意要让每个LOB 实例相应的CHUNK 数减至最少。前面已经看到了,有一个lobindex 用于指向各个块,块越多,索引就越大。如果有一个4MB 的LOB,并使用8KB 的CHUNK,你就至少需要512 个CHUNK来存储这个消息。这也说明,至少需要512 个lobindex 条目指向这些CHUNK。听上去好像没什么,但是你要记住,对于每个LOB 个数的512 倍。另外,这还会影响获取性能,因为与读取更少但更大的CHUNK 相比,现在要花更长的数据来读取和管理许多小CHUNK。我们最终的目标是:使用一个能使“浪费”最少,同时又能高效存储数据的CHUNK大小。

2.2.4. PCTVERSION 子句

DBMS_METADATA 返回的CREATE TABLE 语句包括以下内容:

LOB("TXT") STORE AS ( ... PCTVERSION 10. ... )

多版本一致读、当前读是Oracle数据库具有的独特属性,也是其最重要的特性之一。借助undo表空间的前镜像数据保存,Oracle Server Process可以访问到一些特定时间点(SCN)的数据,作为一致性读取、免于脏数据。

但对于Lob类型而言,一致读问题同样存在。Oracle需要一种保留Lob数据镜像的机制,保存一系列old version。目前,Oracle提供了两种维持机制来进行控制:基于时间的版本保留retention和基于空间的版本保留pctversion。

  1. SQL> select table_name, column_name,pctversion, retention from user_lobs;
  2. TABLE_NAME COLUMN_NAMPCTVERSION RETENTION
  3. ---------- ---------- ---------- ----------
  4. T         CL                          900

LOB在lobsegment 中保留某个百分比的空间来实现LOB 的版本化,直接在lobsegment 本身中维护信息的版本。lobindex 会像其他段一样生成undo,但是lobsegment 不会。

相反,修改一个LOB 时,Oracle 会分配一个新的CHUNK,并且仍保留原来的CHUNK。如果回滚了事务,对LOB 索引所做的修改会回滚,索引将再次指向原来的CHUNK。因此,undo 维护会在LOB 段本身中执行。修改数据时,原来的数据库保持不动,此外会创建新数据。

读LOB 数据时这也很重要。LOB 是读一致的,这与所有其他段一样。如果你在上午9:00 获取一个LOB定位器,你从中获取的LOB 数据就是“上午9:00 那个时刻的数据”。这就像是你在上午9:00 打开了一个游标(一个结果集)一样,所生成的行就是那个时间点的数据行。与结果集类似,即使别人后来修改了LOB数据。在此,Oracle 会使用lobsegment,并使用logindex 的读一致视图来撤销对LOB 的修改,从而提取获取LOB 定位器当时的LOB 数据。它不会使用logsegment 的undo 信息,因为根本不会为logsegment 本身生成undo 信息。

PCTVERSION 控制着用于实现LOB 数据版本化的已分配LOB 空间的百分比(这些数据库块由某个时间点的LOB 所用,并处在lobsegment 的HWM 以下)。对于许多使用情况来说,默认设置10%就足够了,因为在很多情况下,你只是要INSERT 和获取LOB(通常不会执行LOB 的更新;LOB 往往会插入一次,而获取多次)。因此,不必为LOB 版本化预留太多的空间(甚至可以没有)。

不过,如果你的应用确实经常修改LOB,倘若你频繁地读LOB,与此同时另外某个会话正在修改这些LOB,10%可能就太小了。如果处理LOB 时遇到一个ORA-22924错误,解决方案不是增加undo表空间的大小,也不是增加undo保留时间(UNDO_RETENTION),如果你在使用手动undo 管理,那么增加更多RBS 空间也不能解决这个问题。而是应该使用以下命令:

ALTER TABLEtabname MODIFY LOB (lobname) ( PCTVERSION n );

并增加lobsegment 中为实现数据版本化所用的空间大小。

2.2.5. RETENTION 子句

Retention是表示采用基于时间版本保留策略。简单的说,就是尽量保证保留一个时间段内的数据lob版本不会清除掉,即多长时间内来保证一致读。在数据库版本的兼容性版本设置在9.2.0.0以上,并且undo_management参数值为true时,lob是默认直接使用retetion设置的。

需要注意,不能使用这个子句来指定保留时间;而要从数据库的UNDO_RETENTION 设置来继承它。

这个子句与PCTVERSION 子句是互斥的,即RETENTION和 PCTVERSION 只能设置一个,不能两个都设置。

2.2.6. CACHE 子句

前面的DBMS_METADATA返回的CREATETABLE 语句包括以下内容:

LOB("TXT") STORE AS (... NOCACHE ... )

除了NOCACHE,这个选项还可以是CACHE 或CACHE READS。这个子句控制了lobsegment 数据是否存储在缓冲区缓存中。默认的NOCACHE 指示,每个访问都是从磁盘的一个直接读,类似地,每个写/修改都是对大盘的一个直接写。CACHE READS 允许缓存从磁盘读的LOB 数据,但是LOB 数据的写操作必须直接写至磁盘。CACHE 则允许读和写时都能缓存LOB 数据。

在许多情况下,默认设置可能对我们并不合适。如果你只有小规模或中等规模的L O B(例如,使用LOB来存储只有几KB 的描述性字段),对其缓存就很有意义。如果不缓存,当用户更新描述字段时,还必须等待I/O 将数据写指磁盘(将执行一个CHUNK大小的I/O,而且用户要等待这个I/O 完成)。如果你在执行多个LOB 的加载,那么加载每一行时都必须等待这个I/O 完成。所以启用执行LOB 缓存很合理。你可以打开和关闭缓存,来看看会有什么影响:

ALTER TABLEtabname MODIFY LOB (lobname) ( CACHE );

ALTER TABLEtabname MODIFY LOB (lobname) ( NOCACHE );

对于一个规模很多的初始加载,启用LOB 的缓存很有意义,这允许DBWR在后台将LOB 数据写至磁盘,而你的客户应用可以继续加载更多的数据。对于频繁访问或修改的小到中等规模的LOB,缓存就很合理,可以部门让最终用户实时等待物理I/O 完成。不过,对于一个大小为50MB的LOB,把它放在缓存中就没带道理了。

要记住,此时可以充分使用Keep 池或回收池。并非在默认缓存中将lobsegment 数据与所有“常规”数据一同缓存,可以使用保持池或回收池将其分开缓存。采用这种方式,既能缓存LOB 数据,而且不影响系统中现有数据的缓存。

2.2.7. LOB STORAGE 子句

DBMS_METADATA 返回的CREATE TABLE 语句还包括以下内容:

  1. LOB ("TXT")  STORE AS   (…
  2. STORAGE(INITIAL65536
  3. NEXT1048576
  4. MINEXTENTS1
  5. MAXEXTENTS2147483645
  6. PCTINCREASE0
  7. FREELISTS1
  8. FREELISTGROUPS1
  9. BUFFER_POOLDEFAULT))

也就是说,它有一个完整的存储子句,可以用来控制物理存储特征。需要指出,这个存储子句同样适用于lobsegment 和lobindex,对一个段的设置也可以用于另一个段。假设有一个本地管理的表空间,LOB的相关设置将是FREELISTS、FREELIST GROUPS 和BUFFER_POOL。

对LOB 段使用保持池或回收池可能是一个很有用的技术,这样就能缓存LOB 数据,而且不会“破坏”现有的默认缓冲区缓存。并不是将LOB 与常规表一同放在块缓冲区中,可以在SGA 中专门为这些LOB 对象预留一段专用的内存。BUFFER_POOL 子句可以达到这个目的。

2.3 BFILE

BFILE 类型只是操作系统上一个文件的指针。它用于为这些操作系统文件提供只读访问。

注意: 内置包UTL_FILE 也为操作系统文件提供了读写访问。不过它没有使用BFILE 类型。

使用BFILE 时,还有使用一个Oracle DIRECTORY 对象。DIRECTORY 对象只是将一个操作系统目录映射至数据库中的一个“串”或一个名称(以提供可移植性;你可能想使用BFILE 中的一个串,而不是操作系统特定的文件名约定)。

作为一个小例子,下面创建一个带BFILE 列的表,并创建一个DIRECTORY对象,再插入一行,其中引用了文件系统中的一个文件:

  1. SQL> create table t ( id int primarykey,os_file bfile);
  2. Table created.
  3. SQL> create or replace directory my_diras '/tmp/';
  4. Directory created.
  5. SQL> insert into t values ( 1,bfilename( 'MY_DIR', 'test.dbf' ) );
  6. 12.row created.

现在,就可以把BFILE 当成一个LOB 来处理,因为它就是一个LOB。例如,我们可以做下面的工作:

  1. SQL> select dbms_lob.getlength(os_file)from t;
  2. DBMS_LOB.GETLENGTH(OS_FILE)
  3. ---------------------------
  4. 1056768

可以看到所指定的文件大小为1MB。注意,这里故意在INSERT语句中使用了MY_DIR。如果使用混合大小写或小写,会得到以下错误:

  1. SQL> update t set os_file = bfilename('my_dir', 'test.dbf' );
  2. 12.row updated.
  3. SQL> select dbms_lob.getlength(os_file)from t;
  4. select dbms_lob.getlength(os_file) from t
  5. *
  6. ERROR at line 1:
  7. ORA-22285: non-existent directory or filefor GETLENGTH operation
  8. ORA-06512: at "SYS.DBMS_LOB",line 566

这个例子只是说明:Oracle 中的DIRECTORY 对象是标识符,而默认情况下标识符都以大写形式存储。

BFILENAME 内置函数接受一个串,这个串的大小写必须与数据字典中存储的DIRECTORY对象的大小写完全匹配。所以,我们必须在BFILENAME 函数中使用大写,或者在创建DIRECTORY 对象时使用加引号的标识符:

  1. SQL> create or replace directory"my_dir" as '/tmp/';
  2. Directory created.
  3. SQL> select dbms_lob.getlength(os_file)from t;
  4. DBMS_LOB.GETLENGTH(OS_FILE)
  5. ---------------------------
  6. 1056768

不建议使用加引号的标识符;而倾向于在BFILENAME 调用中使用大写。加引号的标识符属于“异类”,可能会在以后导致混淆。

BFILE 在磁盘上占用的空间不定,这取决于DIRECTORY 对象名的文件名的长度。在前面的例子中,所得到的BFILE 长度大约为35 字节。一般来说,BFILE 会占用大约20 字节的开销,再加上DIRECTORY 对象的长度以及文件名本身的长度。

与其他LOB 数据不同,BFILE 数据不是“读一致”的。由于BFILE 在数据库之外管理,对BFILE 解除引用时,不论文件上发生了什么,都会反映到你得到的结果中。所以,如果反复读同一个BFILE,可能会产生不同的结果,这与对CLOB、BLOB 或NCLOB 使用LOB 定位器不同。

三. Move Table 与 LOB

在之前的Blog:

Oracle 高水位(HWM: High Water Mark) 说明

http://blog.csdn.net/tianlesoftware/article/details/4707900

提到解决高水位的一种方法就是Move Table,如果我们的表里有LOB 字段,那么我们在Move 的时候就需要注意一下。

在建立含有lob字段的表时,oracle会自动为lob字段建立两个单独的segment,一个用来存放数据(segment_type=LOBSEGMENT),另一个用来存放索引(segment_type=LOBINDEX)。

我们对表MOVE时,LOG类型字段和该字段的索引不会跟着MOVE,必须要单独来进行MOVE,语法如下如:

SQL>altertable owner.table_name move tablespace tablespace_name lob (lob_column) store as (tablespace tablespace_name);

也可以分2部来走:

SQL> altertable owner.table_name move tablespace tablespace_name;

SQL>altertable owner.table_name move lob(lob_column) store as (tablespacetablespace_name) ;

Move操作会导致表上的索引失效,操作结束后我们需要对索引进行rebuild。这部分可以参考我的Blog:

Oracle alter index rebuild 说明

http://blog.csdn.net/tianlesoftware/article/details/6538928

四. 含有LOB 字段表的迁移示例

这里演示2个不同用户之间的一个迁移,使用expdp/impdp 来实现,有关data pump 参考:

Oracle expdp/impdp 使用示例

http://blog.csdn.net/tianlesoftware/article/details/6260138

1.     先创建directory:

  1. SQL> create directory backup as'/u01/backup';
  2. Directory created.
  3. SQL> select * from dba_directories;
  4. OWNERDIRECTORY_NAME            DIRECTORY_PATH
  5. ----- -------------------------------------------------------------------------
  6. SYS   BACKUP                    /u01/backup

2.     创建2个测试用的用户,每个用户有独立的表空间。

  1. SQL>CREATE TABLESPACEanqing1 DATAFILE  '+DATA/anqing/datafile/anqing01.dbf' SIZE 200M AUTOEXTEND OFF;
  2. SQL>CREATE TABLESPACEanqing2 DATAFILE  '+DATA/anqing/datafile/anqing02.dbf' SIZE 200M AUTOEXTEND OFF;
  3. SQL>create useranqing1 identified by anqing1 default tablespace anqing1;
  4. SQL>create useranqing2 identified by anqing2 default tablespace anqing1;
  5. SQL>grant connect,resource,dba toanqing1,anqing2;

3.     登陆anqing1 用户,创建含有LOB的表:

  1. SYS@anqing1(rac1)> conn anqing1/anqing1;
  2. Connected.
  3. ANQING1@anqing1(rac1)> create table lob1(line number,text clob);
  4. Table created.
  5. ANQING1@anqing1(rac1)> insert into lob1  select line,text from all_source;
  6. 302179 rows created.
  7. ANQING1@anqing1(rac1)>  select segment_name,segment_type,tablespace_name,sum(bytes)/1024/1024||'M'as "SIZE" from user_segments group by segment_name,segment_type,tablespace_name;
  8. SEGMENT_NAME                   SEGMENT_TYPE       TABLESPACE_NAME SIZE
  9. ------------------------------------------------ --------------- --------------
  10. SYS_LOB0000056470C00002$      LOBSEGMENT         ANQING1         27M
  11. LOB1                           TABLE              ANQING1         44M
  12. SYS_IL0000056470C00002$       LOBINDEX           ANQING1         .0625M

这里我们可以看到,我的表LOB1占用空间44M,LOBSEGMENT 占用27M。

4.     采用 REMAP_SCHEMA

4.1 expdp 导出:

  1. [oracle@rac1 backup]$expdp anqing1/anqing1 directory=backup dumpfile=anqing1.dmp logfile=anqing1.log schemas=anqing1;
  2. Export: Release 10.2.0.4.0 - Production onTuesday, 25 October, 2011 20:52:24
  3. Copyright (c) 2003, 2007, Oracle.  All rights reserved.
  4. Connected to: Oracle Database 10gEnterprise Edition Release 10.2.0.4.0 - Production
  5. With the Partitioning, Real ApplicationClusters, OLAP, Data Mining
  6. and Real Application Testing options
  7. FLASHBACK automatically enabled to preservedatabase integrity.
  8. Starting"ANQING1"."SYS_EXPORT_SCHEMA_01":  anqing1/******** directory=backupdumpfile=anqing1.dmp logfile=anqing1.log schemas=anqing1
  9. Estimate in progress using BLOCKS method...
  10. Processing object typeSCHEMA_EXPORT/TABLE/TABLE_DATA
  11. Total estimation using BLOCKS method: 71 MB
  12. Processing object type SCHEMA_EXPORT/USER
  13. Processing object typeSCHEMA_EXPORT/SYSTEM_GRANT
  14. Processing object typeSCHEMA_EXPORT/ROLE_GRANT
  15. Processing object typeSCHEMA_EXPORT/DEFAULT_ROLE
  16. Processing object typeSCHEMA_EXPORT/PRE_SCHEMA/PROCACT_SCHEMA
  17. Processing object typeSCHEMA_EXPORT/TABLE/TABLE
  18. Processing object typeSCHEMA_EXPORT/TABLE/INDEX/INDEX
  19. Processing object typeSCHEMA_EXPORT/TABLE/CONSTRAINT/CONSTRAINT
  20. Processing object typeSCHEMA_EXPORT/TABLE/INDEX/STATISTICS/INDEX_STATISTICS
  21. Processing object typeSCHEMA_EXPORT/TABLE/COMMENT
  22. . . exported"ANQING1"."LOB1"                            51.10 MB  302179 rows
  23. Master table"ANQING1"."SYS_EXPORT_SCHEMA_01" successfullyloaded/unloaded
  24. ******************************************************************************
  25. Dump file set forANQING1.SYS_EXPORT_SCHEMA_01 is:
  26. /u01/backup/anqing1.dmp
  27. Job"ANQING1"."SYS_EXPORT_SCHEMA_01" successfully completed at20:53:06

4.2 impdp 导入:

  1. [oracle@rac1 backup]$impdp  anqing2/anqing2 directory=backupdumpfile=anqing1.dmp logfile=anqing2.log remap_schema=anqing1:anqing2 table_exists_action=replace;
  2. Import: Release 10.2.0.4.0 - Production onTuesday, 25 October, 2011 20:56:15
  3. Copyright (c) 2003, 2007, Oracle.  All rights reserved.
  4. Connected to: Oracle Database 10gEnterprise Edition Release 10.2.0.4.0 - Production
  5. With the Partitioning, Real ApplicationClusters, OLAP, Data Mining
  6. and Real Application Testing options
  7. Master table"ANQING2"."SYS_IMPORT_FULL_01" successfully loaded/unloaded
  8. Starting"ANQING2"."SYS_IMPORT_FULL_01":  anqing2/******** directory=backupdumpfile=anqing1.dmp logfile=anqing2.log remap_schema=anqing1:anqing2table_exists_action=replace
  9. Processing object type SCHEMA_EXPORT/USER
  10. ORA-31684: Object typeUSER:"ANQING2" already exists
  11. Processing object typeSCHEMA_EXPORT/SYSTEM_GRANT
  12. Processing object typeSCHEMA_EXPORT/ROLE_GRANT
  13. Processing object typeSCHEMA_EXPORT/DEFAULT_ROLE
  14. Processing object typeSCHEMA_EXPORT/PRE_SCHEMA/PROCACT_SCHEMA
  15. Processing object typeSCHEMA_EXPORT/TABLE/TABLE
  16. Processing object typeSCHEMA_EXPORT/TABLE/TABLE_DATA
  17. . . imported"ANQING2"."LOB1"                            51.10 MB  302179 rows
  18. Job"ANQING2"."SYS_IMPORT_FULL_01" completed with 1 error(s) at20:57:41

4.3 验证:

  1. ANQING1@anqing1(rac1)> connanqing2/anqing2;
  2. Connected.
  3. ANQING2@anqing1(rac1)> col segment_namefor a30
  4. ANQING2@anqing1(rac1)> coltablespace_name for a15
  5. ANQING2@anqing1(rac1)> selectsegment_name,segment_type,tablespace_name,sum(bytes)/1024/1024||'M' as"SIZE" from user_segments group by segment_name,segment_type,tablespace_name;
  6. SEGMENT_NAME                   SEGMENT_TYPE       TABLESPACE_NAME SIZE
  7. ------------------------------ --------------------------------- --------------
  8. LOB1                           TABLE              ANQING1         44M
  9. SYS_IL0000056648C00002$       LOBINDEX           ANQING1         .0625M
  10. SYS_LOB0000056648C00002$      LOBSEGMENT         ANQING1         27M
  11. ANQING2@anqing1(rac1)>  select owner,table_name,tablespace_name fromall_tables where table_name ='LOB1';
  12. OWNER                          TABLE_NAME                     TABLESPACE_NAME
  13. ------------------------------------------------------------ ---------------
  14. ANQING2                        LOB1                           ANQING1
  15. ANQING1                        LOB1                           ANQING1

我们的数据已经导入到了anqing2用户下,但是该表的物理存储还是存在anqing1的tablespace下面。

4.4 Move Table

将LOB1从anqing1 表空间下面Move 到anqing2下面。

  1. ANQING2@anqing1(rac1)> alter table LOB1move tablespace anqing2;
  2. Table altered.
  3. 验证:
  4. ANQING2@anqing1(rac1)> selectsegment_name,segment_type,tablespace_name,sum(bytes)/1024/1024||'M' as"SIZE" from user_segments group by segment_name,segment_type,tablespace_name;
  5. SEGMENT_NAME                   SEGMENT_TYPE       TABLESPACE_NAME SIZE
  6. ------------------------------------------------ --------------- --------------
  7. SYS_LOB0000056739C00002$      LOBSEGMENT         ANQING1         27M
  8. LOB1                           TABLE              ANQING2         44M
  9. SYS_IL0000056739C00002$       LOBINDEX           ANQING1         .0625M
  10. 9.867                          TEMPORARY          ANQING1         44M
  11. 9.883                          TEMPORARY          ANQING1         .0625M

这里的LOB1 表已经移到anqing2的表空间下了,但是LOBSEGMENT和LOBINDEX 还没有移动。 继续操作:

  1. ANQING2@anqing1(rac1)> alter table lob1move lob(text) store as (tablespace anqing2) ;
  2. Table altered.
  3. ANQING2@anqing1(rac1)> selectsegment_name,segment_type,tablespace_name,sum(bytes)/1024/1024||'M' as"SIZE" from user_segments group by segment_name,segment_type,tablespace_name;
  4. SEGMENT_NAME                   SEGMENT_TYPE       TABLESPACE_NAME SIZE
  5. ------------------------------------------------ --------------- --------------
  6. LOB1                           TABLE              ANQING2         44M
  7. SYS_LOB0000056739C00002$                   LOBSEGMENT         ANQING2         27M
  8. SYS_IL0000056739C00002$       LOBINDEX           ANQING2         .0625M
  9. 9.867                          TEMPORARY          ANQING1         44M
  10. 9.883                          TEMPORARY          ANQING1         .0625M

我这里演示的是不同用户之间的一个迁移,如果是相同用户下的迁移,只需要在操作之前把相关的表空间和用户建好就可以了。

注:第二小结内容出自:<Oracle 9i/10g 编程艺术>