milvus-logo
LFAI
Home
  • User Guide

Clustering Compaction

Clustering compaction is designed to improve search performance and reduce costs in large collections. This guide will help you understand clustering compaction and how this feature can improve search performance.

Overview

Milvus stores incoming entities in segments within a collection and seals a segment when it is full. If this happens, a new segment is created to accommodate additional entities. As a result, entities are arbitrarily distributed across segments. This distribution requires Milvus to search multiple segments to find the nearest neighbors to a given query vector.

Without clustering Compaction Without clustering Compaction

If Milvus can distribute entities among segments based on the values in a specific field, the search scope can be restricted within one segment, thus improving search performance.

Clustering Compaction is a feature in Milvus that redistributes entities among segments in a collection based on the values in a scalar field. To enable this feature, you first need to select a scalar field as the clustering key. This allows Milvus to redistribute entities into a segment when their clustering key values fall within a specific range. When you trigger a clustering compaction, Milvus generates/updates a global index called PartitionStats, which records the mapping relationship between segments and clustering key values.

With Clustering Compaction With Clustering Compaction

Using PartitionStats as a reference, Milvus can prune irrelevant data upon receiving a search/query request that carries a clustering key value and restricting the search scope within the segments mapping to the value, thus improving search performance. For details on performance improvement, refer to Benchmark tests.

Use Clustering Compaction

The Clustering Compaction feature in Milvus is highly configurable. You can choose to trigger it manually or set it to be triggered automatically at intervals by Milvus. To enable clustering compaction, do as follows:

Global Configuration

You need to modify your Milvus configuration file as shown below.

dataCoord:
  compaction:
    clustering:
      enable: true 
      autoEnable: false 
      triggerInterval: 600 
      minInterval: 3600 
      maxInterval: 259200 
      newDataSizeThreshold: 512m 
      timeout: 7200
     
queryNode:
  enableSegmentPrune: true 

datanode:
  clusteringCompaction:
    memoryBufferRatio: 0.1 
    workPoolSize: 8  
common:
  usePartitionKeyAsClusteringKey: true 
  • dataCoord.compaction.clustering

    Configuration ItemDescriptionDefault Value
    enableSpecifies whether to enable clustering compaction.
    Setting this to true if you need to enable this feature for every collection having a clustering key.
    false
    autoEnableSpecifies whether to enable automatically triggered compaction.
    Setting this to true indicates that Milvus compacts the collections having a clustering key at the specified intervals.
    false
    triggerIntervalSpecifies the interval in milliseconds at which Milvus starts clustering compaction.
    This parameter is valid only when autoEnable is set to true.
    -
    minIntervalSpecifies the minimum interval in seconds.
    This parameter is valid only when autoEnable is set to true.
    Setting this to an integer greater than triggerInterval helps avoid repeated compactions within a short period.
    -
    maxIntervalSpecifies the maximum interval in seconds.
    This parameter is valid only when autoEnable is set to true.
    Once Milvus detects that a collection has not been clustering-compacted for a duration longer than this value, it forces a clustering compaction.
    -
    newDataSizeThresholdSpecifies the upper threshold to trigger a clustering compaction.
    This parameter is valid only when autoEnable is set to true.
    Once Milvus detects that the data volume in a collection exceeds this value, it initiates a clustering compaction process.
    -
    timeoutSpecifies the timeout duration for a clustering compaction.
    A clustering compaction fails if its execution time exceeds this value.
    -
  • queryNode

    Configuration ItemDescriptionDefault Value
    enableSegmentPruneSpecifies whether Milvus prunes data by referring to PartitionStats upon receiving search/query requests.
    Setting this to true enables Milvus to prune irrelevant data from segments during a search/query request.
    false
  • dataNode.clusteringCompaction

    Configuration ItemDescriptionDefault Value
    memoryBufferRatioSpecifies the memory buffer ratio for clustering compaction tasks.
    Milvus flushes data when the data size exceeds the allocated buffer size calculated using this ratio.
    -
    workPoolSizeSpecifies the worker pool size for a clustering compaction task.-
  • common

    Configuration ItemDescriptionDefault Value
    usePartitionKeyAsClusteringKeySpecifies whether to use the partition key in collections as the clustering key.
    Setting this to true indicates that the partition key is used as the clustering key.
    You can always override this setting in a collection by explicitly setting a clustering key.
    false

To apply the above changes to your Milvus cluster, please follow the steps in Configure Milvus with Helm and Configure Milvus with Milvus Operators.

Collection Configuration

For clustering compacting in a specific collection, you should select a scalar field from the collection as the clustering key.

default_fields = [
    FieldSchema(name="id", dtype=DataType.INT64, is_primary=True),
    FieldSchema(name="key", dtype=DataType.INT64, is_clustering_key=True),
    FieldSchema(name="var", dtype=DataType.VARCHAR, max_length=1000, is_primary=False),
    FieldSchema(name="embeddings", dtype=DataType.FLOAT_VECTOR, dim=dim)
]

default_schema = CollectionSchema(
    fields=default_fields, 
    description="test clustering-key collection"
)

coll1 = Collection(name="clustering_test", schema=default_schema)

You can use the scalar fields of the following data types as the clustering key: Int8, Int16, Int32, Int64, Float, Double, and VarChar.

Trigger Clustering Compaction

If you have enabled automatic clustering compaction, Milvus automatically triggers the compaction at the specified interval. Alternatively, you can manually trigger the compaction as follows:

coll1.compact(is_clustering=True)
coll1.get_compaction_state(is_clustering=True)
coll1.wait_for_compaction_completed(is_clustering=True)

Benchmark Test

Data volume and query patterns combined determine the performance improvement clustering compaction can bring. An internal benchmark test demonstrates that clustering compaction yields up to a 25-fold improvement in queries per second (QPS).

The benchmark test is on a collection containing entities from a 20-million, 768-dimensional LAION dataset with the key field designated as the clustering key. After clustering compaction is triggered in the collection, concurrent searches are sent until the CPU usage reaches a high water level.

Search Filter Prune Ratio Latency (ms) QPS (reqs/s)
Avg Min Max Median TP99
None 0% 1685 672 2294 1710 2291 17.75
key > 200 and key < 800 40.2% 1045 47 1828 1085 1617 28.38
key > 200 and key < 600 59.8% 829 45 1483 882 1303 35.78
key > 200 and key < 400 79.5% 550 100 985 584 898 54.00
key == 1000 99% 68 24 1273 70 246 431.41

As the search range narrows in the search filters, the prune ratio increases. This means that more entities are skipped during the search process. When comparing the statistics in the first and last rows, you can see that searches without clustering compaction require scanning the entire collection. On the other hand, searches with clustering compaction using a specific key can achieve up to a 25-fold improvement.

Best practices

Here are some tips for you to use clustering compaction efficiently:

  • Enable this for collections with large data volumes. Search performance improves with larger data volumes in a collection. It is a good choice to enable this feature for collections with over 1 million entities.

  • Choose a proper clustering key. You can use scalar fields commonly employed as filtering conditions as the clustering key. For a collection that holds data from multiple tenants, you can utilize the field that distinguishes one tenant from another as the clustering key.

  • Use the partition key as the clustering key. You can set common.usePartitionKeyAsClusteringKey to true if you want to enable this feature for all collections in your Milvus instance or if you still face performance issues in a large collection with a partition key. By doing so, you will have a clustering key and a partition key when you choose a scalar field in a collection as the partition key.

    Note that this setting does not prevent you from choosing another scalar field as the clustering key. The explicitly designated clustering key always takes precedence.

Feedback

Was this page helpful?