自动构建向量索引
自动构建向量索引
向量索引是一种针对向量类型数据而建立的索引机制,类似于传统的标量索引,其最终目的是为了加速向量检索的过程。大部分向量索引不支持增量构建,而全量构建会消耗大量的内存和cpu资源。因此,我们在存储结构上分为stable数据(已经落盘的数据)和delta数据(未落盘的数据)。构建索引时会触发stable数据和delta数据的合并并落盘转化为stable数据,并对stable数据进行全量的索引构建。在检索时,stable部分的数据通过索引进行检索,而delta部分数据通过暴力检索的方式搜索,因此Delta部分的检索的效率往往不高。当增量数据较多时,delta部分的检索会成为瓶颈。因此需要在合适的时机,触发对向量索引进行重新构建。由于数据库表存在多个分片,每个分片的增量变化又并非完全一致,靠DBA人工探测和触发重新构建索引,是非常费力费时的。
为了解决这个问题,我们实现了自动构建向量索引的能力,用户可以根据自己的场景,在表层面设定自动构建策略,并提交给向量数据库。向量数据库会以分片粒度,不断检测当前是否满足了策略的条件,如果满足了策略条件,则自动化发起索引的重新构建。因为策略控制的粒度是分片,故分片之间的索引重建行为并不完全一致,避免了部分分片无谓的重建开销。通过这种方式,可以大大降低客户DBA的向量索引管理负担。
VectorDB当前已经提供了一些常用的自动构建索引策略供用户选择。包括指定时间构建、周期性构建和增量策略构建等方式。
自动构建策略
指定时间的构建策略
客户可以设置在某个指定的时间点触发重新构建向量索引。如果时间点早于当前时间,则会立即触发一次重建向量索引。
- 参数:以字符串形式表示的本地时间,格式支持LOCAL("%Y-%m-%d %H:%M:%S")以及UTC("%Y-%m-%dT%H:%M:%SZ"),例如:"2024-06-06 08:00:00", "2024-06-06T00:00:00Z"。
指定周期的构建策略
客户设定一个循环周期,向量数据库会按照指定的周期进行重建索引。支持指定的时间点开始,按照周期间隔来触发重建索引,例如实践中可以选择资源空闲的半夜2点开始,每24小时构建一次。
如果时间点早于当前时间,则会立即触发一次重建向量索引,而下一次构建索引时间不会发生改变(例如当前时间为5点,设置4点开始每两小时构建一次,则会在当前时间5点和下个时间6点进行重建索引)。
为了避免资源浪费,当数据增量(增加或者减少)100条以内,不会触发自动构建索引。
- 参数一:以整型表示的周期,单位为秒,为了避免客户误设很短的周期,严重浪费资源,周期值不能小于3600(即1个小时)。
- 参数二:以字符串形式表示的本地时间,格式支持LOCAL("%Y-%m-%d %H:%M:%S")以及UTC("%Y-%m-%dT%H:%M:%SZ"),例如:"2024-06-06 08:00:00", "2024-06-06T00:00:00Z"。不设置特定时间时,则第一次构建会发生在当前时间加上一个周期的时间。
指定增量的构建策略
客户设定一个增量或者增量百分比,VectorDB会定期检查分片上的数据量,如果增加或减少了一定的行数或者行数百分比,则会重建索引。以下两个参数同时设置或只设置一个均可,只要其中一个满足条件便会触发
- 参数一:以无符号整数表示的增量行数,增加或者减少这个数量都会重建索引。为了避免客户误设很小的行数,严重浪费资源,行数不能低于10000。
- 参数二:以双精度浮点型表示的增量行数百分比,增加或者减少这个数量百分比都会重建索引,由于分片数量很大时较小的值也会有意义,因此没有设置最小值限制。不建议在分片行数较少时设置,可能导致频繁的重建索引造成资源浪费。
如何设置自动构建索引策略
在本小节中,我们以Python SDK的使用方式来展示自动构建索引的使用。
在SDK中,VectorDB提供了一个默认的周期性策略,即每24小时自动构建一次(从上次构建的时间点开始计算)。在SDK中设置自动构架策略时,如果没有指定构建策略,则自动使用该默认策略。构建策略及默认构建策略定义如下所示:
class AutoBuildTiming:
def __init__(self, timing):
self._timing = timing
class AutoBuildPeriodical:
def __init__(self, period_s, timing=""):
self._period_s = period_s
self._timing = timing
class AutoBuildRowCountIncrement:
def __init__(self, row_count_increment=0, row_count_increment_ratio=0):
self._row_count_increment = row_count_increment
self._row_count_increment_ratio = row_count_increment_ratio
AutoBuildTiming("2024-06-06 00:00:00")
AutoBuildPeriodical(24 * 3600,"2024-06-06 00:00:00")
AutoBuildRowCountIncrement(row_count_increment=20000, row_count_increment_ratio=0.5)
# 默认策略
DefaultAutoBuildPeriodical = 24 * 3600
DefaultAutoBuildPolicy = AutoBuildPeriodical(DefaultAutoBuildPeriodical)
在SDK中,有三个入口可以设置向量索引自动构建策略,分别如下:
- 在创建表时通过向量索引参数来设置
- 在创建索引时通过向量索引参数来设置
- 通过
modify_index
接口设置
下面以Python SDK为例,展示一下上述三个入口的使用方法。
- 建表时设置自动构建索引
import pymochow
from pymochow.configuration import Configuration
from pymochow.auth.bce_credentials import BceCredentials
from pymochow.model.schema import Schema, Field, SecondaryIndex, VectorIndex, HNSWParams, AutoBuildTiming, AutoBuildPeriodical, AutoBuildRowCountIncrement
from pymochow.model.enum import FieldType, IndexType, MetricType, ServerErrCode
from pymochow.model.table import Partition, Row, AnnSearch, HNSWSearchParams
if __name__ == "__main__":
account = 'root'
api_key = '$您的API密钥'
endpoint = '$您的实例端点' #例如:'http://127.0.0.1:5287'
config = Configuration(credentials=BceCredentials(account, api_key),
endpoint=endpoint)
client = pymochow.MochowClient(config)
database = 'book'
table_name = 'book_segments'
db = client.create_database(database)
fields = []
fields.append(Field("id", FieldType.STRING, primary_key=True,
partition_key=True, auto_increment=False, not_null=True))
fields.append(Field("bookName", FieldType.STRING, not_null=True))
fields.append(Field("vector", FieldType.FLOAT_VECTOR, not_null=True, dimension=3))
indexes = []
vindex = VectorIndex(index_name="vector_idx", index_type=IndexType.HNSW,
field="vector", metric_type=MetricType.L2,
params=HNSWParams(m=32, efconstruction=200),
auto_build=True,
auto_build_index_policy=AutoBuildTiming("2024-06-06 00:00:00"))
indexes.append(vindex)
# 如果是免费版 replication 只能设置为 1
db.create_table(
table_name=table_name,
replication=2,
partition=Partition(partition_num=3),
schema=Schema(fields=fields, indexes=indexes)
)
- 新建索引时设置自动构建索引
import pymochow
import time
from pymochow.configuration import Configuration
from pymochow.auth.bce_credentials import BceCredentials
from pymochow.model.schema import Schema, Field, SecondaryIndex, VectorIndex, HNSWParams, AutoBuildTiming, AutoBuildPeriodical, AutoBuildRowCountIncrement
from pymochow.model.enum import FieldType, IndexType, MetricType, ServerErrCode
from pymochow.model.enum import TableState, IndexState
from pymochow.model.table import Partition, Row, AnnSearch, HNSWSearchParams
if __name__ == "__main__":
account = 'root'
api_key = '$您的API密钥'
endpoint = '$您的实例端点' #例如:'http://127.0.0.1:5287'
config = Configuration(credentials=BceCredentials(account, api_key),
endpoint=endpoint)
client = pymochow.MochowClient(config)
database = 'book'
table_name = 'book_segments'
db = client.create_database(database)
fields = []
fields.append(Field("id", FieldType.STRING, primary_key=True,
partition_key=True, auto_increment=False, not_null=True))
fields.append(Field("bookName", FieldType.STRING, not_null=True))
fields.append(Field("vector", FieldType.FLOAT_VECTOR, not_null=True, dimension=3))
db.create_table(
table_name=table_name,
replication=2,
partition=Partition(partition_num=3),
schema=Schema(fields=fields, indexes=[])
)
while True:
time.sleep(2)
table = db.describe_table(table_name)
if table.state == TableState.NORMAL:
break
table = db.table('book_segments')
indexes = []
vindex = VectorIndex(index_name="vector_idx",
index_type=IndexType.HNSW,
field="vector", metric_type=MetricType.L2,
params=HNSWParams(m=32, efconstruction=200),
auto_build=True,
auto_build_index_policy=AutoBuildTiming("2024-06-06 00:00:00"))
indexes.append(vindex)
table.create_indexes(indexes)
- 通过
modify_index
接口设置。
import pymochow
import time
from pymochow.configuration import Configuration
from pymochow.auth.bce_credentials import BceCredentials
from pymochow.model.schema import Schema, Field, SecondaryIndex, VectorIndex, HNSWParams, AutoBuildTiming, AutoBuildPeriodical, AutoBuildRowCountIncrement
from pymochow.model.enum import FieldType, IndexType, MetricType, ServerErrCode
from pymochow.model.enum import TableState, IndexState
from pymochow.model.table import Partition, Row, AnnSearch, HNSWSearchParams
if __name__ == "__main__":
account = 'root'
api_key = '$您的API密钥'
endpoint = '$您的实例端点' #例如:'http://127.0.0.1:5287'
config = Configuration(credentials=BceCredentials(account, api_key),
endpoint=endpoint)
client = pymochow.MochowClient(config)
database = 'book'
table_name = 'book_segments'
db = client.create_database(database)
fields = []
fields.append(Field("id", FieldType.STRING, primary_key=True,
partition_key=True, auto_increment=False, not_null=True))
fields.append(Field("bookName", FieldType.STRING, not_null=True))
fields.append(Field("vector", FieldType.FLOAT_VECTOR, not_null=True, dimension=3))
db.create_table(
table_name=table_name,
replication=2,
partition=Partition(partition_num=3),
schema=Schema(fields=fields, indexes=[])
)
while True:
time.sleep(2)
table = db.describe_table(table_name)
if table.state == TableState.NORMAL:
break
table = db.table('book_segments')
indexes = []
vindex = VectorIndex(index_name="vector_idx",
index_type=IndexType.HNSW,
field="vector", metric_type=MetricType.L2,
params=HNSWParams(m=32, efconstruction=200))
indexes.append(vindex)
table.create_indexes(indexes)
table.modify_index(index_name="vector_idx", auto_build=True,
auto_build_index_policy=AutoBuildTiming("2024-06-06 00:00:00"))
如何查询自动构建索引策略
在SDK中,可以通过describe_index
接口查询已经设置的自动构建索引策略。下面以Python SDK为例展示用法:
import pymochow
import time
from pymochow.configuration import Configuration
from pymochow.auth.bce_credentials import BceCredentials
from pymochow.model.schema import Schema, Field, SecondaryIndex, VectorIndex, HNSWParams, AutoBuildTiming, AutoBuildPeriodical, AutoBuildRowCountIncrement
from pymochow.model.enum import FieldType, IndexType, MetricType, ServerErrCode
from pymochow.model.enum import TableState, IndexState
from pymochow.model.table import Partition, Row, AnnSearch, HNSWSearchParams
if __name__ == "__main__":
account = 'root'
api_key = '$您的API密钥'
endpoint = '$您的实例端点' #例如:'http://127.0.0.1:5287'
config = Configuration(credentials=BceCredentials(account, api_key),
endpoint=endpoint)
client = pymochow.MochowClient(config)
database = 'book'
table_name = 'book_segments'
db = client.create_database(database)
fields = []
fields.append(Field("id", FieldType.STRING, primary_key=True,
partition_key=True, auto_increment=False, not_null=True))
fields.append(Field("bookName", FieldType.STRING, not_null=True))
fields.append(Field("vector", FieldType.FLOAT_VECTOR, not_null=True, dimension=3))
indexes = []
vindex = VectorIndex(index_name="vector_idx", index_type=IndexType.HNSW,
field="vector", metric_type=MetricType.L2,
params=HNSWParams(m=32, efconstruction=200),
auto_build=True,
auto_build_index_policy=AutoBuildTiming("2024-06-06 00:00:00"))
indexes.append(vindex)
db.create_table(
table_name=table_name,
replication=2,
partition=Partition(partition_num=3),
schema=Schema(fields=fields, indexes=indexes)
)
while True:
time.sleep(2)
table = db.describe_table(table_name)
if table.state == TableState.NORMAL:
break
table = db.table('book_segments')
index = table.describe_index("vector_idx")
print("index: {}".format(index.to_dict()))