.replace extents command

Applies to: ✅ Azure Data Explorer

This command drops and moves extents in a single transaction within the context of a specific database. The command drops any specified extents from the destination table and moves specified extents from source tables to the destination table.

Note

Data shards are called extents, and all commands use "extent" or "extents" as a synonym. For more information on extents, see Extents (data shards) overview.

Permissions

You must have at least Table Admin permissions for the source and destination tables.

Restrictions

  • Both source and destination tables must be in the context database.
  • All extents specified by the ExtentsToDropQuery are expected to belong to the destination table.
  • All columns in the source tables are expected to exist in the destination table with the same name and data type.
  • If the destination table is a source table of a materialized view, the command might fail since the materialized view can't process the records in the moved extents. See more details in the materialized views limitations page. You can work around this error by setting a new ingestion time during the move command. See setNewIngestionTime in supported properties.

Syntax

.replace [async] extents in table DestinationTableName [ with (PropertyName = PropertyValue [, ...])] <| {ExtentsToDropQuery},{ExtentsToMoveQuery}

Learn more about syntax conventions.

Parameters

Name Type Required Description
async string If specified, the command runs asynchronously.
DestinationTableName string ✔️ The name of the table to which to move the extents.
FromDate datetime The query window start date.
ToDate datetime The query window end date.
PropertyName, PropertyValue string One or more Supported properties.
ExtentsToDropQuery string ✔️ The results of this query must include the ExtentId column, which contains the extent IDs to be removed from the destination table.
ExtentsToMoveQuery string ✔️ The results of this query must include the ExtentId and TableName columns, which contains the source tables and extent IDs to be moved to the destination table.

Supported properties

Property name Type Required Description
setNewIngestionTime bool If set to true, a new ingestion time is assigned to all records in extents being moved. This is useful when records are processed by workloads that depend on database cursors, such as materialized views and continuous data export.
extentCreatedOnFrom datetime ✔️ Apply on extents created after this point in time.
extentCreatedOnTo datetime ✔️ Apply on extents created before this point in time.

Note

For better performance, set extentCreatedOnFrom and extentCreatedOnTo parameters to the smallest possible range.

Returns

When the command is run synchronously, a table with the following schema is returned.

Output parameter Type Description
OriginalExtentId string A unique identifier (GUID) for the original extent in the source table that was moved to the destination table, or the extent in the destination table that was dropped.
ResultExtentId string A unique identifier (GUID) for the result extent moved from the source table to the destination table. Empty, if the extent was dropped from the destination table. Upon failure: "Failed."
Details string Includes the failure details if the operation fails.

When the command is run asynchronously, an operation ID (GUID) is returned. Monitor the operation's status with the .show operations command, and retrieve the results of a successful execution with the .show operation details command.

Note

The command will fail if extents returned by the ExtentsToDropQuery query don't exist in the destination table. This may happen if the extents were merged before the replace command was executed. To make sure the command fails on missing extents, check that the query returns the expected ExtentIds. The first example will fail if the extent to drop doesn't exist in table MyOtherTable. The second example, however, will succeed even though the extent to drop doesn't exist, since the query to drop didn't return any extent IDs.

Examples

Move all extents in a specified creation time range from two tables

Move all extents from two specific tables (MyTable1, MyTable2) in a specified creation time range to table MyOtherTable, and drop all extents in MyOtherTable tagged with drop-by:MyTag:

.replace extents in table MyOtherTable with (extentCreatedOnFrom=datetime(2023-03-10), extentCreatedOnTo=datetime(2023-03-12)) <|
    {
        .show table MyOtherTable extents where tags has 'drop-by:MyTag'
    },
    {
        .show tables (MyTable1,MyTable2) extents
    }

Sample output

OriginalExtentId ResultExtentId Details
e133f050-a1e2-4dad-8552-1f5cf47cab69 0d96ab2d-9dd2-4d2c-a45e-b24c65aa6687
cdbeb35b-87ea-499f-b545-defbae091b57 a90a303c-8a14-4207-8f35-d8ea94ca45be
4fcb4598-9a31-4614-903c-0c67c286da8c 97aafea1-59ff-4312-b06b-08f42187872f
2dfdef64-62a3-4950-a130-96b5b1083b5a 0fb7f3da-5e28-4f09-a000-e62eb41592df

Move all extents in a specified creation time range from one table to another, drop specific extent

Move all extents in a specified creation time range from one specific table (MyTable1) to table MyOtherTable, and drop a specific extent in MyOtherTable, by its ID:

.replace extents in table MyOtherTable with (extentCreatedOnFrom=datetime(2023-03-10), extentCreatedOnTo=datetime(2023-03-12)) <|
    {
        print ExtentId = "2cca5844-8f0d-454e-bdad-299e978be5df"
    },
    {
        .show table MyTable1 extents 
    }
.replace extents in table MyOtherTable with (extentCreatedOnFrom=datetime(2023-03-10), extentCreatedOnTo=datetime(2023-03-12)) <|
    {
        .show table MyOtherTable extents
        | where ExtentId == guid(2cca5844-8f0d-454e-bdad-299e978be5df) 
    },
    {
        .show table MyTable1 extents 
    }

Implement an idempotent logic

Implement an idempotent logic so that Kusto drops extents from table t_dest only if there are extents to move from table t_source to table t_dest:

.replace async extents in table t_dest with (extentCreatedOnFrom=datetime(2023-03-10), extentCreatedOnTo=datetime(2023-03-12)) <|
{
    let any_extents_to_move = toscalar( 
        t_source
        | where extent_tags() has 'drop-by:blue'
        | summarize count() > 0
    );
    let extents_to_drop =
        t_dest
        | where any_extents_to_move and extent_tags() has 'drop-by:blue'
        | summarize by ExtentId = extent_id()
    ;
    extents_to_drop
},
{
    let extents_to_move = 
        t_source
        | where extent_tags() has 'drop-by:blue'
        | summarize by ExtentId = extent_id(), TableName = 't_source'
    ;
    extents_to_move
}