Operations: Server: How to Compact a Database
- Use the CompactDatabaseOperation to compact a database.
- You can choose what should be compacted: documents and/or listed indexes.
The compacting operation is executed asynchronously, and during this operation the database will be offline.
Syntax
// Define the compact settings
CompactSettings settings = new CompactSettings
{
// Database to compact
DatabaseName = "Northwind",
// Setting 'Documents' to false will compact only the specified indexes
Documents = false,
// Specify which indexes to compact
Indexes = new[] { "Orders/Totals", "Orders/ByCompany" },
// Optimize indexes is Lucene's feature to gain disk space and efficiency
// Set whether to skip this optimization when compacting the indexes
SkipOptimizeIndexes = false
};
// Define the compact operation, pass the settings
IServerOperation<OperationIdResult> compactOp = new CompactDatabaseOperation(settings);
// Execute compaction by passing the operation to Maintenance.Server.Send
Operation operation = documentStore.Maintenance.Server.Send(compactOp);
// Wait for operation to complete
operation.WaitForCompletion();
// Get all indexes names in the database using the 'GetIndexNamesOperation' operation
// Use 'ForDatabase' if the target database is different than the default database defined on the store
string[] allIndexNames =
documentStore.Maintenance.ForDatabase("Northwind")
.Send(new GetIndexNamesOperation(0, int.MaxValue));
// Define the compact settings
CompactSettings settings = new CompactSettings
{
DatabaseName = "Northwind", // Database to compact
Documents = true, // Compact all documents
Indexes = allIndexNames, // All indexes will be compacted
SkipOptimizeIndexes = true // Skip Lucene's indexes optimization
};
// Define the compact operation, pass the settings
IServerOperation<OperationIdResult> compactOp = new CompactDatabaseOperation(settings);
// Execute compaction by passing the operation to Maintenance.Server.Send
Operation operation = documentStore.Maintenance.Server.Send(compactOp);
// Wait for operation to complete
operation.WaitForCompletion();
Parameters | ||
---|---|---|
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
// Get all member nodes in the database-group using the 'GetDatabaseRecordOperation' operation
List<string> allMemberNodes =
documentStore.Maintenance.Server.Send(new GetDatabaseRecordOperation("Northwind"))
.Topology.Members;
// Define the compact settings as needed
CompactSettings settings = new CompactSettings
{
// Database to compact
DatabaseName = "Northwind",
//Compact all documents in database
Documents = true
};
// Execute the compact operation on each member node
foreach (string nodeTag in allMemberNodes)
{
// Define the compact operation, pass the settings
IServerOperation<OperationIdResult> compactOp = new CompactDatabaseOperation(settings);
// Execute the operation on a specific node
// Use `ForNode` to specify the node to operate on
Operation operation = documentStore.Maintenance.Server.ForNode(nodeTag).Send(compactOp);
// Wait for operation to complete
operation.WaitForCompletion();
}
Example II
// get all index names
string[] indexNames = store.Maintenance.Send(new GetIndexNamesOperation(0, int.MaxValue));
CompactSettings settings = new CompactSettings
{
DatabaseName = "Northwind",
Documents = true,
Indexes = indexNames
};
// compact entire database: documents + all indexes
Operation operation = store.Maintenance.Server.Send(new CompactDatabaseOperation(settings));
operation.WaitForCompletion();
Example III
-
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.
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);
}
}