RECREATE_INDEX_ONLINE
Recreates the specified index, or recreates the passed-in index partition if the index is local partitioned.
For global nonpartitioned indexes, this is a one-step procedure. For local partitioned indexes, this procedure must be run separately on every partition after first using CREATE_SHADOW_INDEX to create a shadow policy (or metadata). This procedure is only supported in Enterprise Edition of Oracle AI Database.
The following changes are not supported:
-
Transitioning from non-composite domain index to composite, or changing the composite domain index columns.
-
Rebuilding indexes that have partitioned index tables, for example,
$I,$P,$K.
Syntax
CTX_DDL.RECREATE_INDEX_ONLINE(
idx_name IN VARCHAR2,
parameter_string IN VARCHAR2 default NULL,
parallel_degree IN NUMBER default 1,
partition_name IN VARCHAR2 default NULL
);
idx_name
The name of a valid CONTEXT indextype.
parameter_string
If the index is a global nonpartitioned index, specify the same index-level parameter string as in ALTER INDEX. Must start with REPLACE, if it is not NULL. Optionally specify SWAP or NOSWAP. The default is SWAP.
parallel_degree
Reserved for future use. Specify the degree of parallelism. Parallel operation is not supported in the current release.
partition_name
Specify the name of a valid index partition for a local partitioned index. Otherwise, the default is NULL. If the index is partitioned, then first pass a partition name, and then specify the partition-level parameter string for ALTER INDEX REBUILD PARTITION.
Examples
Example 8-5 Recreate Simple Global Index
The following example creates an index idx with a BASIC_LEXER-based preference us_lexer. It then recreates the index with a new MULTI_LEXER based preference m_lexer in one step. You can use this one step approach when you do not mind that a query might fail for a small window of time at the end of the operation, and DML might get blocked at the beginning for a short time and again at the end.
/* create lexer and original index */
exec ctx_ddl.create_preference('us_lexer','basic_lexer');
create index idx on tbl(text) indextype is ctxsys.context
parameters('lexer us_lexer');
/* create a new lexer */
begin
ctx_ddl.create_preference('e_lexer','basic_lexer');
ctx_ddl.set_attribute('e_lexer','base_letter','yes');
ctx_ddl.create_preference('m_lexer','multi_lexer');
ctx_ddl.add_sub_lexer('m_lexer','default','us_lexer');
ctx_ddl.add_sub_lexer('m_lexer','e','e_lexer');
end;
/
/* add new language column to the table for multi-lexer */
alter table tbl add(lang varchar2(10) default 'us');
/* recreate index online with the new multip-lexer */
exec ctx_ddl.recreate_index_online('idx',
'replace lexer m_lexer language column lang');
Example 8-6 Local Index Recreate with All-At-Once Swap
The following example creates a local partitioned index idxp with a basic lexer us_lexer. It has two index partitions idx_p1 and idx_p2. It then recreates a local partitioned index idxp online with partition idx_p1, which will have a new storage preference new_store. The swapping of the partition metadata and index partition data occur at the end. In this example, queries spanning multiple partitions return consistent results across partitions when recreate is in process, except at the end when EXCHANGE_SHADOW_INDEX is running. The extra space required is the combined index size of partition idx_p1 and idx_p2.
/* create a basic lexer and a local partition index with the lexer*/
exec ctx_ddl.create_preference('us_lexer','basic_lexer');
create index idxp on tblp(text) indextype is ctxsys.context local
(partition idx_p1,
partition idx_p2)
parameters('lexer us_lexer');
/* create new preferences */
begin
ctx_ddl.create_preference('my_store','basic_storage');
ctx_ddl.set_attribute('my_store','i_table_clause','tablespace tbs');
end;
/
begin
ctx_ddl.create_preference('e_lexer','basic_lexer');
ctx_ddl.set_attribute('e_lexer','base_letter','yes');
ctx_ddl.create_preference('m_lexer','multi_lexer');
ctx_ddl.add_sub_lexer('m_lexer','default','us_lexer');
ctx_ddl.add_sub_lexer('m_lexer','e','e_lexer');
end;
/
/* add new language column */
alter table tblp add column (lang varchar2(10) default 'us');
/* create a shadow policy with a new lexer */
exec ctx_ddl.create_shadow_index('idxp', null,
'replace lexer m_lexer language column lang');
/* recreate every index partition online without swapping */
exec ctx_ddl.recreate_index_online('idxp',
'replace storage my_store NOSWAP', 1, 'idx_p1');
exec ctx_ddl.recreate_index_online('idxp','replace NOSWAP',1,'idx_p2');
/* exchange in shadow index partition all at once */
exec ctx_ddl.exchange_shadow_index('idxp',
'idx_p1') /* exchange index partition data*/
exec ctx_ddl.exchange_shadow_index('idxp',
'idx_p2') /* exchange index partition data*/
/* exchange in shadow index metadata */
exec ctx_ddl.exchange_shadow_index('idxp')
Example 8-7 Local Index Recreate with Per-Partition Swap
This example performs the same tasks as Example 8-6, except that each index partition is swapped in as it is completed. Queries across all partitions may return inconsistent results in this example.
/* create a basic lexer and a local partition index with the lexer*/
exec ctx_ddl.create_preference('us_lexer','basic_lexer');
create index idxp on tblp(text) indextype is ctxsys.context local
(partition idx_p1,
partition idx_p2)
parameters('lexer us_lexer');
/* create new preferences */
begin
ctx_ddl.create_preference('my_store','basic_storage');
ctx_ddl.set_attribute('my_store','i_table_clause','tablespace tbs');
end;
/
begin
ctx_ddl.create_preference('e_lexer','basic_lexer');
ctx_ddl.set_attribute('e_lexer','base_letter','yes');
ctx_ddl.create_preference('m_lexer','multi_lexer');
ctx_ddl.add_sub_lexer('m_lexer','default','us_lexer');
ctx_ddl.add_sub_lexer('m_lexer','e','e_lexer');
end;
/
/* add new language column */
alter table tblp add column (lang varchar2(10) default 'us');
/* create a shadow policy with a new lexer *
exec ctx_ddl.create_shadow_index('idxp',
'replace lexer m_lexer language column lang');
/* recreate every index partition online and swap (default) */
exec ctx_ddl.recreate_index_online('idxp',
'replace storage my_store', 1, 'idx_p1');
exec ctx_ddl.recreate_index_online('idxp', 'replace SWAP', 1, 'idx_p2',
/* exchange in shadow index metadata */
exec ctx_ddl.exchange_shadow_index('idxp')
Example 8-8 Scheduled Local Index Recreate with All-At-Once Swap
This example shows the incremental recreation of a local partitioned index, where partitions are all swapped at the end.
/* create a basic lexer and a local partition index with the lexer*/
exec ctx_ddl.create_preference('us_lexer','basic_lexer');
create index idxp on tblp(text) indextype is ctxsys.context local
(partition idx_p1,
partition idx_p2)
parameters('lexer us_lexer');
/* create new preferences */
begin
ctx_ddl.create_preference('my_store','basic_storage');
ctx_ddl.set_attribute('my_store','i_table_clause','tablespace tbs');
end;
/
begin
ctx_ddl.create_preference('e_lexer','basic_lexer');
ctx_ddl.set_attribute('e_lexer','base_letter','yes');
ctx_ddl.create_preference('m_lexer','multi_lexer');
ctx_ddl.add_sub_lexer('m_lexer','default','us_lexer');
ctx_ddl.add_sub_lexer('m_lexer','e','e_lexer');
end;
/
/* add new language column */
alter table tblp add column (lang varchar2(10) default 'us');
/* create a shadow policy with a new lexer *
exec ctx_ddl.create_shadow_index('idxp',
'replace lexer m_lexer language column lang');
/* create shadow partition with new storage preference */
exec ctx_ddl.recreate_index_online('idxp', 'replace storage ctxsys.default_storage nopopulate',1,'idx_p1');
exec ctx_ddl.recreate_index_online('idxp', 'replace storage ctxsys.default_storage nopopulate',1,'idx_p2');
declare
idxid integer;
ixpid integer;
begin
select idx_id into idxid from ctx_user_indexes
where idx_name = 'IDXP';
select ixp_id into ixpid from ctx_user_index_partitions
where ixp_index_name = 'IDXP'
and ixp_index_partition_name = 'IDX_P1';
/* populate pending */
ctx_ddl.populate_pending('RIO$'||idxid, 'RIO$'||idxid||'#'||ixpid);
/* incremental sync
ctx_ddl.sync_index('RIO$'||idxid, null, 'RIO$'||idxid||'#'||ixpid,
maxtime=>400);
/* more incremental sync until no more pending rows */
select ixp_id into ixpid from ctx_user_index_partitions
where ixp_index_name = 'IDXP'
and ixp_index_partition_name = 'IDX_P2';
/* populate pending */
ctx_ddl.populate_pending('RIO$'||idxid, 'RIO$'||idxid||'#'||ixpid);
/* incremental sync
ctx_ddl.sync_index('RIO$'||idxid, null, 'RIO$'||idxid||'#'||ixpid,
maxtime=>400);
/* more incremental sync until no more pending rows */
end;
/
exec ctx_ddl.exchange_shadow_index('idxp','idx_p1');
exec ctx_ddl.exchange_shadow_index('idxp','idx_p2');
exec ctx_ddl.exchange_shadow_index('idxp');
Example 8-9 Schedule Local Index Recreate with Per-Partition Swap
For incremental recreate where partitions are swapped as they becomes available, follow the steps in example Example 8-8, except instead of waiting until all syncs are finished before starting exchange shadow index, EXCHANGE_SHADOW_INDEX is done for each partition right after sync is finished.
Notes
-
Using RECREATE_INDEX_ONLINE with Global Nonpartitioned Indexes:
For global indexes, this procedure provides a one-step process to recreate an index online. It recreates an index, with new preference values, while preserving base table DML and query capability during the recreate process.
Because the new index is created alongside the existing index, this operation requires additional storage roughly equal to the size of the existing index.
-
DML Behavior:
Because this procedure is performed online, DML on the base table are permitted during this operation, and are processed as normal. All DML statements that occur during
RECREATE_INDEX_ONLINEare logged into an online pending queue.Towards the end of the recreate operation, there will be a short duration when DML will fail with an error being raised stating that the index is in an in-progress status. DML may stop responding again during the process, and the duration will depend on how many DML are logged in the online pending queue since the start of the recreate process.
Note that after the recreate index operation is complete, new information, from all the DML that becomes pending since
RECREATE_INDEX_ONLINEstarted, may not be immediately reflected. As with creating an index withINDEXTYPEISctxsys.contextONLINE, the index should be synchronized after the recreate index operation is complete, to bring it fully up-to-date. -
Sync and Optimize Behavior:
Syncs issued against the index during the recreate operation are processed against the old, existing data. Syncs are also blocked during the same window when queries return errors.
After running
RECREATE_INDEX_ONLINE, you must call theSYNC_INDEXoperation to synchronize any DML that occurs during the build of the shadow index. If you have specifiedSYNC(ON COMMIT)orSYNC(EVERY), then the sync occurs automatically. However, if you have specifiedSYNC(MANUAL), then you must manually invokeSYNC_INDEX.Optimize commands issued against the index during the recreate operation return immediately without error and without processing.
-
Query Behavior:
During the recreate operation, the index can be queried normally most of the time. Queries return results based on the existing index and policy (or metadata) until after the final swap.
There is a short interval towards the end of
RECREATE_INDEX_ONLINEwhen queries will return an error indicating that the column is not indexed. This duration should be short for regular queries. It is mainly the time taken for swapping data segments of the shadow index tables and the index tables, plus the time to delete all the rows in the pending queue. This is the same window of time when DML will fail.During
RECREATE_INDEX_ONLINE, if you issue DML statements and synchronize them, then you will be able to see the new rows when you query on the existing index. However, afterRECREATE_INDEX_ONLINEfinishes (swapping completes and query is on the new index) and before sync is performed, it is possible that you will not be able to query on the new rows, which once could be queried on the old index.Transactional queries are not supported.
-
Using RECREATE_INDEX_ONLINE with Local Partitioned Indexes:
If the index is local partitioned, you cannot recreate index in one step. You must first create a shadow policy, and then run this procedure for every partition. You can specify
SWAPorNOSWAPto indicate whetherRECREATE_INDEX_ONLINEpartition will swap the index partition data and index partition metadata or not. If the partition was built withNOSWAP, then another call toEXCHANGE_SHADOW_INDEXmust be invoked later against this partition.This procedure can also be used to update the metadata (for example, storage preference) of each partition when you specify
NOPOPULATEin the parameter string. This is useful for incremental building of a shadow index through time-limited sync.If
NOPOPULATEis specified, thenNOSWAPis silently enforced. -
NOSWAP Behavior:
During the recreate of the index partition, since no swapping is performed, queries on the partition are processed regularly. Until the swapping stage is reached, queries spanning multiple partitions return consistent results across partitions.
DML and sync are processed normally. Running optimize on partitions that are being recreated, or that have been built (but not swapped), simply returns without doing anything. Running optimize on a partition that has not been rebuilt processes normally.
As with a global index, when all of the partitions use
NOSWAP, the additional storage requirement is roughly equal to the size of the existing index. -
SWAP Behavior:
Because index partition data and metadata are swapped after index recreate, queries that span multiple partitions will not return consistent results from partition to partition, but will always be correct with respect to each index partition. There is also a short interval towards the end of partition recreate, when the index partition is swapped, during which a query will return a “column not indexed” error.
When partitions are recreated with
SWAP, the additional storage requirement for the operation is equal to the size of the existing index partition.DML on the partition is blocked. Sync is also blocked during swapping.
-
Restrictions:
The
RECREATE_INDEX_ONLINEandCREATE_SHADOW_INDEXprocedures do not support section group with theXML_ENABLEattribute onCONTEXTindexes. Doing so results in the “DRG-10521: Operation not supported with XML_ENABLE on a CONTEXT Index” error.The
RECREATE_INDEX_ONLINEandCREATE_SHADOW_INDEXprocedures are not supported for search indexes.
Related Topics