Operations: Server: How to Compact a Database

  • The compaction operation removes empty gaps on the disk that still occupy space after deletes.

  • You can choose what should be compacted: documents and/or listed indexes.

  • The operation compacts on one node.
    If you wish to compact all nodes in the database group, the command must be sent to each node separately.

  • From Client API: Use the CompactDatabaseOperation.
    To compact on more than one node, the command must be sent to each node by specifying ForNode(<nodeTag>).

  • From Studio: Compaction can be triggered from the Storage Report view.
    The operation will compact the database only on the node being viewed (node info is in the Studio footer).

The database will be offline during compaction.

The compacting operation is executed asynchronously, and during this operation, the database will be offline.

Syntax

public CompactDatabaseOperation(CompactSettings compactSettings)

public class CompactSettings
{
    public string DatabaseName { get; set; }

    public bool Documents { get; set; }

    public string[] Indexes { get; set; }
}

DatabaseName is a mandatory parameter.
You must also specify Documents and/or Indexes.

Parameters Type Description
DatabaseName string Name of a database to compact
Documents bool Indicates if documents should be compacted
Indexes string[] List of index names to compact

Example I - Compact specific indexes

The following example shows how to compact only specific indexes. Documents are also set to be compacted.

CompactSettings settings = new CompactSettings
{
    DatabaseName = "Northwind",
    // If true, the documents will also be compacted.
    Documents = true,
    // Only the specified indexes will compact.
    Indexes = new[] { "Orders/Totals", "Orders/ByCompany" } 
};
// You can use 'ForNode(<nodeTag>)' to specify on which node to compact.
// If ForNode() is not used, RavenDB will operate by default on the preferred node.
Operation operation = store.Maintenance.Server.ForNode("A")
    .Send(new CompactDatabaseOperation(settings));
operation.WaitForCompletion();

// To compact on all nodes, the above command must be sent to each node separately.

Example II - Compact all indexes

The following example shows how to compact all of the indexes and documents in the database.

// Get all index names in the database.
string[] indexNames = store.Maintenance.Send(new GetIndexNamesOperation(0, int.MaxValue));

CompactSettings settings = new CompactSettings
{
    DatabaseName = "Northwind",
    // If true, documents will also be compacted.
    Documents = true,
    // 'indexNames' contains all of the index names.
    Indexes = indexNames
};
// You can use 'ForNode(<nodeTag>)' to specify on which node to compact.
// If ForNode() is not used, RavenDB will operate by default on the preferred node.
Operation operation = store.Maintenance.Server.ForNode("A")
    .Send(new CompactDatabaseOperation(settings));
operation.WaitForCompletion();

// To compact on all nodes, the above command must be sent to each node separately.

Example III - Compact a database that is external to the store

  • CompactDatabaseOperation automatically runs on the store's database.
    If we try to compact a different database, the process will succeed only if the database resides on the cluster's first online node.
    Trying to compact a non-default database on a different node will fail with an error such as -
    "500 Internal Server Error : System.InvalidOperationException , Cannot compact database 'name' on node A, because it doesn't reside on this node."

  • To solve this, we can explicitly identify the database we want to compact by providing its name to CompactDatabaseOperation as in the following example.

    // To compact a database other than the store's database, we need to explicitly provide 
    // its name to the store's Request Executor.  
    using (var store = new DocumentStore
    {
        Urls = new[] { "http://localhost:8080" },
        Database = "sampleDB" // the store's database
    }.Initialize())
    {
        store.GetRequestExecutor().GetPreferredNode().Wait();
    
        const string DBToCompact = "NonDefaultDB"; // the database we want to compact
        string[] indexNames = store.Maintenance.Send(new GetIndexNamesOperation(0, int.MaxValue));
    
        var compactOperation = new CompactDatabaseOperation(new Raven.Client.ServerWide.CompactSettings
        {
            DatabaseName = DBToCompact,
            Documents = true,
            Indexes = indexNames
        });
    
        // Get request executor for our DB
        var reqEx = store.GetRequestExecutor(DBToCompact);
    
        using (reqEx.ContextPool.AllocateOperationContext(out var context))
        {
            var compactCommand = compactOperation.GetCommand(store.Conventions, context);
            reqEx.Execute(compactCommand, context);
        }
    }

Compaction Triggers Documents Compression

Compaction triggers documents compression on all existing documents in the collections that are configured for compression.

If compression is defined on a collection, and if you don't trigger compaction,
only new or modified documents will be compressed.