一篇文章学会Milvus【Docker 中运行 Milvus(Windows),Python实现对Milvus的操作,源代码案例,已经解决巨坑】【程序员猫爪】

一篇文章学会Milvus【Docker 中运行 Milvus(Windows),Python实现对Milvus的操作,源代码案例,已经解决巨坑】【程序员猫爪】

    • 一、Milvus 是什么?【程序员猫爪】
      • 1、Milvus 是一种高性能、高扩展性的向量数据库,可在从笔记本电脑到大规模分布式系统等各种环境中高效运行。它既可以开源软件的形式提供,也可以云服务的形式提供。
      • 2、Milvus 支持各种类型的搜索功能,以满足不同用例的需求:
      • 3、应用程序接口和 SDK
      • 4、稀疏向量
      • 5、安全和授权
      • 6、人工智能集成
    • 二、快速入门 Milvus Lite【注意这个只能在Ubuntu和MacOS里面使用】这里我们在Ubuntu里面使用【程序员猫爪】
      • 1、Python安装 Milvus
      • 2、相关问题?查询的时候不能直接通过对应的单词进行查询吗 ?
    • 三、在 Docker 中运行 Milvus(Windows)【程序员猫爪】
      • 1、在 Docker 中运行 etcd,minio,Milvus
      • 2、启动attu
      • 3、我们还可以访问minio对象存储的管理界面,查看milvus存储内容。
    • 四、创建collection并执行向量搜索【程序员猫爪】
      • 1、创建collection
      • 字段类型
      • 向量字段
      • 一致性
      • 2、写入数据
      • 3、创建索引
      • 4、加载索引
      • 5、查看数据
      • 6、向量搜索
    • 五、索引【程序员猫爪】
      • 1、索引简介
      • 2、索引分类
      • 索引类型
      • 度量类型
      • 3、创建索引-使用attu创建hnsw索引
      • 4、创建索引-使用pymilvus创建索引
    • 六、索引-FLAT索引【程序员猫爪】
      • 1、通过Attu来创建
      • 2、通过pymilvus来创建
    • 七、对元数据进行解析【程序员猫爪】
    • 八、milvus元数据存储规则【程序员猫爪】
      • 1、创建新的索引,并添加一部分数据
      • 2、milvus元数据在etcd的存储解析
        • database
        • collection
        • field
        • hid字段:
        • embedding字段:
        • partition
        • index
        • segment-index
        • resource_group
      • 3、milvus的向量数据和索引数据在s3的存储
        • data在s3的存储
        • index在s3的存储
    • 九、架构和组件介绍【程序员猫爪】
      • 接入层
      • 协调器服务
      • 根协调器 (RootCoord)
      • 查询协调器 (QueryCoord)
      • 数据协调器 (DataCoord)
      • 工作节点
        • 查询节点(querynode)
        • 数据节点(datanode)
        • 索引节点(indexnode)
      • 存储
        • 元存储
        • 对象存储
        • 日志代理
    • 十、Milvus的管理和使用【数据库管理】【程序员猫爪】
      • 1、管理数据库
      • 2、创建数据库
      • 3、使用数据库
      • 4、列出数据库
      • 5、删除数据库
    • 十一、collection操作【程序员猫爪】
      • 1、创建collection
      • 2、删除collection
      • 3、加载collection
      • 4、释放collection
      • 5、描述collection
    • 十二、向量搜索search【程序员猫爪】
      • 1、插入数据
      • 2、向量搜索
    • 十三、批量向量搜索【程序员猫爪】
    • 十四、分区搜索【程序员猫爪】

一、Milvus 是什么?【程序员猫爪】

为什么要学习向量数据库,向量数据库如何结合大模型实现智能搜索
Milvus 是一个开源的向量数据库,专门用于管理大量的非结构化数据,如图像、视频、音频和文本等。它能够高效地进行相似度搜索,这使得它成为结合大模型实现智能搜索的理想选择。以下是 Milvus 如何与大模型结合以实现智能搜索的一些关键点:

  1. 特征提取
    大模型(例如预训练的语言模型或视觉模型)可以用来从原始数据中提取出有意义的特征表示。这些特征通常被转换为高维向量,即嵌入(embeddings)。

  2. 存储和索引
    提取的嵌入随后可以存储在 Milvus 数据库中。Milvus 支持多种类型的索引结构,比如 IVF_FLAT, HNSW 等,它们能加速大规模向量的相似性搜索过程。

  3. 查询处理
    当用户提交查询时,同样的大模型会将查询也转化为相应的嵌入形式。然后,这个查询向量可以在 Milvus 中快速找到最相似的数据点,即执行近似最近邻(Approximate Nearest Neighbor, ANN)搜索。

  4. 结果排序和过滤
    搜索结果可以根据相似度得分进行排序,并且可以应用额外的过滤条件来进一步精炼结果集。例如,只返回特定时间范围内的文档或者来自某些类别的图片。

  5. 集成和优化
    整个系统可能需要对大模型生成的嵌入进行调优,以确保它们适合于 Milvus 的索引和搜索机制。此外,还可以通过分布式部署、缓存策略等方式提高系统的性能和响应速度。

  6. 持续学习
    如果是在线应用场景,系统应该支持增量学习或迁移学习的能力,以便随着新数据的到来不断更新模型参数,保持搜索的相关性和准确性。

  7. 安全性和隐私保护
    在设计智能搜索解决方案时,还需要考虑如何保证数据的安全性和用户的隐私,特别是在涉及到敏感信息的情况下。

综上所述,通过将 Milvus 与大模型相结合,可以构建出一种高效的智能搜索系统,该系统不仅能够处理大量复杂的数据类型,而且还能提供精准、快速的搜索体验。

1、Milvus 是一种高性能、高扩展性的向量数据库,可在从笔记本电脑到大规模分布式系统等各种环境中高效运行。它既可以开源软件的形式提供,也可以云服务的形式提供。

Milvus 是 LF AI & Data Foundation 下的一个开源项目,以 Apache 2.0 许可发布。大多数贡献者都是高性能计算(HPC)领域的专家,擅长构建大型系统和优化硬件感知代码。核心贡献者包括来自 Zilliz、ARM、NVIDIA、AMD、英特尔、Meta、IBM、Salesforce、阿里巴巴和微软的专业人士。

  • 非结构化数据

非结构化数据(包括图像、视频、音频和自然语言)是不遵循预定义模型或组织方式的信息。此类数据约占全球数据的80%,
可以使用各种人工智能(AI)和机器学习(ML)模型将其转换为向量。

  • 嵌入向量

嵌入向量是非结构化数据(例如电子邮件、物联网传感器数据、Instagram照片、蛋白质结构等)的特征抽象。从数学上讲,
嵌入向量是浮点数或二进制数组。现代嵌入技术用于将非结构化数据转换为嵌入向量。

  • 向量相似性搜索

向量相似性搜索是将向量与数据库进行比较以找到与查询向量最相似的向量的过程。近似最近邻(ANN)搜索算法用于加速搜
索过程。如果两个嵌入向量非常相似,则意味着原始数据源也相似。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

2、Milvus 支持各种类型的搜索功能,以满足不同用例的需求:

  • ANN 搜索:查找最接近查询向量的前 K 个向量。
  • 过滤搜索:在指定的过滤条件下执行 ANN 搜索。
  • 范围搜索:查找查询向量指定半径范围内的向量。
  • 混合搜索:基于多个向量场进行 ANN 搜索。
  • 全文搜索:基于 BM25 的全文搜索。
  • Rerankers:根据附加标准或辅助算法调整搜索结果顺序,完善初始 ANN 搜索结果。
  • 获取:根据主键检索数据。
  • 查询使用特定表达式检索数据。

3、应用程序接口和 SDK

  • RESTful API(官方)
  • PyMilvus(Python SDK)(官方)
  • Go SDK(官方)
  • Java SDK(官方)
  • Node.js(JavaScript)SDK(官方)
  • C#(微软提供)
  • 高级数据类型
  • 除了原始数据类型外,Milvus 还支持各种高级数据类型及其各自适用的距离度量。

4、稀疏向量

  • 二进制向量

  • 支持 JSON

  • 数组支持

  • 距离度量

  • 加速

  • 搜索算法 Milvus 支持一系列可调整的索引和搜索算法。有关详情,请参阅内存索引、磁盘索引和GPU 索引。

  • 分区和分区键 分区是 Milvus Collection 的子分区。你可以选择一个标量字段作为分区键,以获得更好的搜索性能。有关详情,请参阅管理分区和使用分区密钥。

  • 可调一致性模型 一致性可确保每个 Milvus 节点或副本在给定时间写入或读取数据时拥有相同的数据视图。在 Milvus 中进行 ANN 搜索时,可以轻松调整一致性级别。有关详细信息,请参阅一致性。

  • 高通量数据导入 要将大量数据导入 Milvus,而不是一个接一个地插入,可以考虑使用我们的高通量数据导入工具。有关详情,请参阅准备源数据和导入数据。

  • 多租户支持 Milvus 实现了许多面向多租户场景的功能,包括 Partition Key、Clustering Key 等。有关详情,请参阅多租户策略。

5、安全和授权

  • 可调一致性模型 一致性可确保每个 Milvus 节点或副本在给定时间写入或读取数据时拥有相同的数据视图。在 Milvus 中进行 ANN 搜索时,您可以轻松调整一致性级别。有关详细信息,请参阅一致性。

  • 数据隔离和资源控制 对于多租户场景,数据隔离是基本的安全要求。Milvus 实现了多种功能来解决您的安全问题。详情请参阅管理资源组和 集群压缩。

6、人工智能集成

  • Embeddings 模型集成 Embedding 模型将非结构化数据转换为其在高维数据空间中的数字表示,以便您能将其存储在 Milvus 中。目前,PyMilvus(Python SDK)集成了多个嵌入模型,以便您能快速将数据准备成向量嵌入。有关详情,请参阅嵌入概述。

  • Reranker 模型集成 在信息检索和生成式人工智能领域,Reranker 是优化初始搜索结果顺序的重要工具。PyMilvus 也集成了几种 Rerankers 模型,以优化初始搜索返回结果的顺序。详情请参考Rerankers 概述。

  • LangChain 和其他人工智能工具集成 在 GenAI 时代,LangChain 等工具受到了应用程序开发人员的广泛关注。作为核心组件,Milvus 通常在此类工具中充当向量存储。要了解如何将 Milvus 集成到您喜爱的人工智能工具中,请参阅我们的集成和教程。

二、快速入门 Milvus Lite【注意这个只能在Ubuntu和MacOS里面使用】这里我们在Ubuntu里面使用【程序员猫爪】

1、Python安装 Milvus

pip install -U pymilvus
touch milvus_demo.py
touch milvus_demo.db
from pymilvus import MilvusClient
import numpy as np

client = MilvusClient("./milvus_demo.db")
client.create_collection(
    collection_name="demo_collection",
    dimension=384  # The vectors we will use in this demo has 384 dimensions
)

docs = [
    "Artificial intelligence was founded as an academic discipline in 1956.",
    "Alan Turing was the first person to conduct substantial research in AI.",
    "Born in Maida Vale, London, Turing was raised in southern England.",
]

vectors = [[ np.random.uniform(-1, 1) for _ in range(384) ] for _ in range(len(docs)) ]
data = [ {"id": i, "vector": vectors[i], "text": docs[i], "subject": "history"} for i in range(len(vectors)) ]
res = client.insert(
    collection_name="demo_collection",
    data=data
)

res = client.search(
    collection_name="demo_collection",
    data=[vectors[0]],
    filter="subject == 'history'",
    limit=2,
    output_fields=["text", "subject"],
)
print(res)

res = client.query(
    collection_name="demo_collection",
    filter="subject == 'history'",
    output_fields=["text", "subject"],
)
print(res)

res = client.delete(
    collection_name="demo_collection",
    filter="subject == 'history'",
)
print(res)

这段代码使用了pymilvus库与Milvus向量数据库进行交互,执行了创建集合、插入数据、搜索数据、查询数据以及删除数据的操作。以下是对每一行代码的详细解释:

from pymilvus import MilvusClient
import numpy as np
  • pymilvus库中导入MilvusClient类,用于连接和操作Milvus数据库。
  • 导入numpy库,用于生成随机向量数据。
client = MilvusClient("./milvus_demo.db")
  • 创建一个MilvusClient实例,连接到本地的Milvus数据库,数据库文件路径为"./milvus_demo.db"
client.create_collection(
    collection_name="demo_collection",
    dimension=384  # The vectors we will use in this demo has 384 dimensions
)
  • 使用create_collection方法在Milvus数据库中创建一个新的集合,名为"demo_collection"。这个集合中的向量维度是384维,后续插入的向量数据都要遵循这个维度要求。
docs = [
    "Artificial intelligence was founded as an academic discipline in 1956.",
    "Alan Turing was the first person to conduct substantial research in AI.",
    "Born in Maida Vale, London, Turing was raised in southern England."
]
  • 定义一个字符串列表docs,包含了三条历史相关的文本信息。
vectors = [[ np.random.uniform(-1, 1) for _ in range(384) ] for _ in range(len(docs)) ]
  • 使用列表推导式生成随机向量数据。对于每一条文本,都生成一个长度为384的向量,向量中的每个元素都在-11之间随机取值。
  • 随机数的方式对文本每一句进行向量化,设置对应每一句的向量值,
data = [ {"id": i, "vector": vectors[i], "text": docs[i], "subject": "history"} for i in range(len(vectors)) ]
  • 构建一个数据列表data,每个元素都是一个字典,包含了id(自增序号)、vector(对应的向量)、text(文本内容)以及subject(主题,这里都是"history") 。
  • 这行代码就是把文本数据与对应的向量数据整合起来,构建成一个方便后续处理的数据集合。每个字典元素都是一个完整的数据单元,其中文本信息 (text) 和其专属的向量表示 (vector) 精准配对,再搭配上自增的唯一标识 (id) 与固定主题 (subject),这种结构化的数据集合非常适合批量插入数据库,确保数据的完整性与关联性得以维持,方便后续进行查询、检索等操作。
res = client.insert(
    collection_name="demo_collection",
    data=data
)
  • 使用insert方法将数据插入到"demo_collection"集合中,插入成功后会返回一个结果对象res
res = client.search(
    collection_name="demo_collection",
    data=[vectors[0]],
    filter="subject == 'history'",
    limit=2,
    output_fields=["text", "subject"]
)
print(res)
  • "demo_collection"集合中执行搜索操作:
    • data参数传入要搜索的向量,这里是vectors列表中的第一个向量。
    • filter参数用于过滤数据,只搜索subject字段为"history"的记录。
    • limit指定最多返回两条匹配的结果。
    • output_fields定义了要返回的字段,这里是"text""subject"。最后打印搜索结果。
res = client.query(
    collection_name="demo_collection",
    filter="subject == 'history'",
    output_fields=["text", "subject"]
)
print(res)
  • "demo_collection"集合中执行查询操作:
    • filter同样用于过滤,只查询subject"history"的记录。
    • output_fields指定返回的字段,打印查询得到的结果。
res = client.delete(
    collection_name="demo_collection",
    filter="subject == 'history'"
)
print(res)
  • "demo_collection"集合中执行删除操作,删除所有subject字段值为"history"的记录,打印删除操作的结果。

2、相关问题?查询的时候不能直接通过对应的单词进行查询吗 ?

在这段代码的设定下,不能直接通过对应的单词进行查询,原因如下:

  • 数据存储方式:代码向Milvus数据库插入数据时,存储的核心是向量数据以及与之关联的文本、主题等元数据,并没有针对单词构建索引或者存储独立的单词信息。数据库重点利用向量之间的相似度来检索数据,而非基于单词文本做精确匹配。例如,数据集合里是为整段文本生成的向量,没有单独拆分出单词存储。
  • Milvus的特性:Milvus是一个向量数据库,擅长处理向量空间内的相似性搜索,它并不是传统的关系型数据库(像MySQL), 没有基于单词的文本查找语法。在这里执行的搜索操作是基于向量相似性的,先筛选出满足subject == 'history'条件的向量数据,再找出和给定查询向量[vectors[0]]相近的记录,最后返回对应textsubject字段。
  • 当前代码目的:这段代码主要用于演示向量数据库的基本操作,如集合创建、向量插入、基于向量和简单过滤条件的搜索。要是想实现单词查询,需要额外集成自然语言处理技术,比如先用分词工具拆分文本,将单词单独索引存储,然后编写适配的查询逻辑,这远超当前代码简单演示的范畴。

必须输入完整的向量?

  1. 在这个示例中是这样的情况
    • 从代码实现角度来看,client.search方法的设计在这个例子里要求输入向量来进行搜索。这是因为Milvus作为向量数据库,其核心搜索机制是基于向量相似度的。在这个代码片段中,它是在向量空间中寻找与给定向量(这里是vectors[0])相似的其他向量,同时结合filter条件(subject == 'history')进一步筛选结果。
    • 这种基于向量的搜索方式类似于在高维空间中找到离给定“点”(向量)较近的其他“点”(符合主题条件的向量)。而且它返回的结果数量由limit参数控制,并且只返回指定的output_fields["text", "subject"])中的内容。
  2. 在实际应用场景中可能有其他方式
    • 如果想要实现更灵活的搜索,比如基于单词或者部分文本内容的搜索,通常需要在应用层做更多的处理。例如,可以先对文本进行预处理,将文本内容(单词、短语等)和向量建立更复杂的映射关系。
    • 还可以结合其他技术,如自然语言处理中的关键词提取技术。当用户输入一个单词时,先提取该单词对应的向量(可能通过预训练的词向量模型获取),然后再使用这个向量作为输入进行搜索。不过这需要额外的开发工作,如集成词向量模型、构建新的搜索逻辑等,并且要确保这种搜索方式与Milvus本身的向量搜索机制能够很好地协同工作。

三、在 Docker 中运行 Milvus(Windows)【程序员猫爪】

1、在 Docker 中运行 etcd,minio,Milvus

由于milvus依赖etcd和minio,因此需要先启动这2个组件。同样也使用docker进行启动。
etcd:用来存储milvus的元数据。
minio:用来存储milvus的向量数据和索引数据。
安装好docker-desktop以后在某个文件夹下创建docker-compose.yml

version: '3.5'

services:
  etcd:
    container_name: milvus-etcd
    image: quay.io/coreos/etcd:v3.5.5
    environment:
      - ETCD_AUTO_COMPACTION_MODE=revision
      - ETCD_AUTO_COMPACTION_RETENTION=1000
      - ETCD_QUOTA_BACKEND_BYTES=4294967296
      - ETCD_SNAPSHOT_COUNT=50000
    volumes:
      - ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/etcd:/etcd
    command: etcd -advertise-client-urls=http://127.0.0.1:2379 -listen-client-urls http://0.0.0.0:2379 --data-dir /etcd
    healthcheck:
      test: ["CMD", "etcdctl", "endpoint", "health"]
      interval: 30s
      timeout: 20s
      retries: 3

  minio:
    container_name: milvus-minio
    image: minio/minio:RELEASE.2023-03-20T20-16-18Z
    environment:
      MINIO_ACCESS_KEY: minioadmin
      MINIO_SECRET_KEY: minioadmin
    ports:
      - "9001:9001"
      - "9000:9000"
    volumes:
      - ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/minio:/minio_data
    command: minio server /minio_data --console-address ":9001"
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
      interval: 30s
      timeout: 20s
      retries: 3

  standalone:
    container_name: milvus-standalone
    image: milvusdb/milvus:v2.4.15
    command: ["milvus", "run", "standalone"]
    security_opt:
    - seccomp:unconfined
    environment:
      ETCD_ENDPOINTS: etcd:2379
      MINIO_ADDRESS: minio:9000
    volumes:
      - ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/milvus:/var/lib/milvus
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:9091/healthz"]
      interval: 30s
      start_period: 90s
      timeout: 20s
      retries: 3
    ports:
      - "19530:19530"
      - "9091:9091"
    depends_on:
      - "etcd"
      - "minio"

networks:
  default:
    name: milvus

在上述文件对应的目录下使用如下命令【这里需要科学上网】

docker-compose up -d

在这里插入图片描述

注意启动以后可能会出现如下问题
win系统SpaceAgent的开机启动项spaceagent.exe这个占用端口号
在这里插入图片描述

然后后台启动这些容器:

 docker-compose up -d-d 代表后台启动

其它一些相关命令:

docker-compose ps  查看容器
docker-compose stop 停止容器
docker-compose start 启动容器
docker-compose down  停止并删除容器(特别注意以免误删容器)

使用ps命令查看容器:
如果看到healthy状态,说明容器内的服务可以正常使用了
在这里插入图片描述
在这里插入图片描述

这时候已经完成milvus服务的启动。如果想查看milvus的日志,可以使用如下命令:

docker logs -f milvus-standalone

milvus-standalone为容器的名称
在这里插入图片描述

2、启动attu

attu为milvus的一款图形化管理工具,非常方便对milvus的一些管理。
启动attu
注意对应的IP地址必须填写局域网的ip,127.0.0.1不能访问

docker run -d --name=attu -p 8000:3000 -e MILVUS_URL=192.168.1.32:19530 zilliz/attu:v2.3.9

http://localhost:8000/#/connect

在这里插入图片描述
在这里插入图片描述
到这里我们就完成了整个standalone的安装部署过程。

3、我们还可以访问minio对象存储的管理界面,查看milvus存储内容。

http://localhost:9001/login

账户和密码:minioadmin
在这里插入图片描述
在这里插入图片描述

四、创建collection并执行向量搜索【程序员猫爪】

1、创建collection

collection属于某个db。
api参考docs:
https://milvus.io/docs

使用attu创建collection。
保证我们的容器都是在运行状态
在这里插入图片描述
创建collection

Milvus字段类型,向量字段,以及一致性介绍
Milvus 是一个开源的向量数据库,它主要用于相似度搜索任务,比如在图像、音频、视频和文本等非结构化数据上的应用。Milvus 支持多种字段类型,并且特别为高效地存储和查询高维向量设计了向量字段。下面我将介绍 Milvus 的字段类型、向量字段以及一致性模型。

字段类型

在 Milvus 中,可以创建不同类型的字段以适应不同的数据需求:

  1. 主键(Primary Key):每个集合中的记录必须有一个唯一标识符作为主键。
  2. 布尔型(Boolean):用于存储真或假的值。
  3. 整数型(Int32, Int64):用于存储32位或64位的整数值。
  4. 浮点型(Float, Double):用于存储单精度或双精度浮点数。
  5. 字符串型(VarChar):用于存储可变长度的字符数据。
  6. 向量型(FloatVector, BinaryVector):用于存储浮点数或二进制格式的向量数据。

向量字段

向量字段是 Milvus 的核心特性之一,专门用于存储和处理向量数据。向量字段有两种类型:

  • FloatVector:用于表示由浮点数组成的向量。
  • BinaryVector:用于表示二进制编码的向量,通常用于哈希算法产生的特征。

这些向量字段可以被索引以加速相似度搜索。Milvus 支持多种索引类型,如 IVF_FLAT, IVF_SQ8, IVF_PQ 等,它们能够优化向量数据的检索效率。

一致性

Strong Consistency (强一致性)

  • 定义:所有读取操作都会返回最新的写入结果。
  • 特点:最严格的一致性形式,但在分布式系统中可能会影响性能。
    Session Consistency (会话一致性)
  • 定义:在一个客户端的会话期间,任何更新之后的读取都将看到该更新的结果。
  • 特点:适用于需要在会话期间保持一致性的场景。
    Bounded Staleness (有限陈旧性)
  • 定义:允许读取的数据有一定的陈旧性,但这个陈旧性是有限制的。
  • 特点:可以在一定程度上牺牲一致性来提高性能。
    Eventual Consistency (最终一致性)
  • 定义:不要求每次读取都能获取最新的写入结果,但保证经过一定时间后所有的更新都会传播到所有节点。
  • 特点:适用于对实时性要求不高但希望最终达到一致性的场景。

2、写入数据

使用pymilvus创建collection,并写入数据

import uuid
import numpy as np
from pymilvus import (
    connections,
    FieldSchema, CollectionSchema, DataType,
    Collection, utility
)

# 数据库连接参数
COLLECTION_NAME = "hello_milvus"  # 集合名称
MILVUS_HOST = "192.168.1.32"  # Milvus服务器地址
MILVUS_PORT = 19530  # Milvus服务器端口
USERNAME = ""  # 如果需要认证,请填写用户名
PASSWORD = ""  # 如果需要认证,请填写密码
NUM_ENTITIES, DIMENSION = 1000, 128  # 插入实体数量和向量维度


def generate_uuids(number_of_uuids):
    """生成指定数量的UUID"""
    return [str(uuid.uuid4()) for _ in range(number_of_uuids)]


def connect_to_milvus():
    """尝试连接到Milvus数据库"""
    try:
        print("正在连接到Milvus...")
        connections.connect("default", host=MILVUS_HOST, port=MILVUS_PORT, user=USERNAME, password=PASSWORD)
        print("成功连接到Milvus.")
    except Exception as e:
        print(f"连接到Milvus失败: {e}")
        raise


def create_collection_if_not_exists():
    """如果集合不存在,则创建一个新的集合"""
    if utility.has_collection(COLLECTION_NAME):
        print(f"集合 '{COLLECTION_NAME}' 已经存在.")
        return Collection(COLLECTION_NAME)

    fields = [
        FieldSchema(name="id", dtype=DataType.INT64, is_primary=True, auto_id=False),  # 主键字段
        FieldSchema(name="random_value", dtype=DataType.DOUBLE),  # 随机值字段
        FieldSchema(name="comment", dtype=DataType.VARCHAR, max_length=200),  # 注释字段
        FieldSchema(name="embedding", dtype=DataType.FLOAT_VECTOR, dim=DIMENSION)  # 向量嵌入字段
    ]

    schema = CollectionSchema(fields, description=f"{COLLECTION_NAME} 是一个演示用的集合")
    collection = Collection(name=COLLECTION_NAME, schema=schema, consistency_level="Bounded", shards_num=1)
    print(f"创建了集合 '{COLLECTION_NAME}'.")
    return collection


def insert_entities(collection):
    """插入实体数据到集合中"""
    rng = np.random.default_rng(seed=19530)
    entities = [
        [i for i in range(NUM_ENTITIES)],  # id字段,整数序列
        rng.random(NUM_ENTITIES).tolist(),  # random_value字段,随机浮点数列表
        generate_uuids(NUM_ENTITIES),  # comment字段,UUID字符串列表
        rng.random((NUM_ENTITIES, DIMENSION)).tolist()  # embedding字段,随机浮点数二维数组
    ]

    try:
        print("正在插入实体...")
        collection.insert(entities)
        print("实体插入完成.")
        print("正在刷新集合...")
        collection.flush()
        print("刷新完成.")
    except Exception as e:
        print(f"插入实体或刷新时出错: {e}")
        raise


if __name__ == "__main__":
    connect_to_milvus()  # 建立与Milvus的连接
    collection = create_collection_if_not_exists()  # 创建集合(如果不存在)
    insert_entities(collection)  # 插入实体数据

在这里插入图片描述
在这里插入图片描述

刷新页面我们可以看到对应的内容创建成功
在这里插入图片描述
在这里插入图片描述

3、创建索引

在这里插入图片描述
在这里插入图片描述
创建成功
在这里插入图片描述

4、加载索引

在这里插入图片描述
在这里插入图片描述

5、查看数据

collection加载进内存后才可以预览和查看表数据。
在这里插入图片描述

6、向量搜索

随机生成一个向量进行搜索
在这里插入图片描述
使用原始向量进行搜索(精确搜索)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

五、索引【程序员猫爪】

1、索引简介

索引的作用是加速大型数据集上的查询。
目前,向量字段仅支持一个索引,即只能创建一个索引。
milvus支持的向量索引类型大部分使用近似最近邻搜索算法(ANNS,approximate nearest neighbors
search) 。ANNS 的核心思想不再局限于返回最准确的结果,而是仅搜索目标的邻居。 ANNS 通过在可
接受的范围内牺牲准确性来提高检索效率

2、索引分类

  • milvus支持内存索引、磁盘索引。
  • 根据实现方法,ANNS向量索引可以分为4类:
    基于树的索引
    基于图的索引
    基于哈希的索引
    基于量化的索引
  • 根据数据类型,支持2种类型的索引:
    floating-point embeddings
    SCANN、IVF_FLAT、IVF_PQ、IVF_SQ8、FLAT、HNSW、ANNOY、AUTOINDEX、DISKANN
    binary embeddings
    BIN_FLAT、BIN_IVF_FLAT
    Milvus 是一个用于相似性搜索和管理的向量数据库,它支持多种索引类型和度量类型来优化不同应用场景下的向量相似性搜索。以下是 Milvus 支持的一些常见的索引类型和度量类型:

索引类型

  1. FLAT (Flat Index)

    • 没有构建额外索引结构,进行暴力搜索。
    • 适用于小规模数据集或需要精确结果的场景。
  2. IVF_FLAT (Inverted File Index with Flat sub-indexes)

    • 使用倒排文件将向量分配到多个簇中,每个簇内部使用 FLAT 索引。
    • 平衡了搜索效率和准确性。
  3. IVF_SQ8 (Inverted File Index with Scalar Quantization)

    • 在 IVF 的基础上对每个簇内的向量进行量化压缩。
    • 减少了存储空间,可能会影响一些精度。
  4. IVF_PQ (Inverted File Index with Product Quantization)

    • 结合了 IVF 和 PQ 技术,提供了高效的近似最近邻搜索。
    • 适合大规模数据集。
  5. HNSW (Hierarchical Navigable Small World Graphs)

    • 基于图结构的索引方法,提供快速的近似最近邻查询。
    • 对高维稀疏数据有效。
  6. ANNOY (Approximate Nearest Neighbors Oh Yeah)

    • 使用随机投影树构建索引,适用于离线构建和在线查询场景。
  7. RHNSW (Reconfigurable HNSW)

    • HNSW 的变体,允许在索引构建后调整参数以适应不同的查询需求。

度量类型

  • L2 (Euclidean distance)

    • 计算两个向量之间的欧几里得距离,用于衡量向量间的差异。
  • IP (Inner Product)

    • 计算两个向量的内积,常用于余弦相似度计算(当向量被归一化时)。
  • COSINE

    • 计算两个向量之间的余弦相似度,表示它们方向上的相似性。

不同的索引和度量类型适用于不同的应用场景和数据特性。选择合适的索引和度量类型可以显著提高查询性能和效果。请注意,随着 Milvus 的发展,可能会引入新的索引和度量类型,或者对现有的实现进行改进。

3、创建索引-使用attu创建hnsw索引

我们需要吧之前创建的索引释放一下
在这里插入图片描述
删除对应的索引
在这里插入图片描述

在这里插入图片描述
创建对应的索引
在这里插入图片描述
在这里插入图片描述

  • 索引类型选择HNSW。
  • 度量类型有3种:
    L2(欧式距离)
    本质上,欧几里得距离测量连接 2 个点的线段的长度。
    IP(内积,点积)
    如果您使用 IP 来计算相似度,则必须对其进行标准化。归一化后,内积等于余弦相似度。
    COSINE(余弦相似度)
    余弦相似度使用两组向量之间的角度的余弦来衡量它们的相似程度。

4、创建索引-使用pymilvus创建索引

因为没有加载所以这里不需要释放
在这里插入图片描述
直接删除
在这里插入图片描述
在这里插入图片描述
在向量字段创建一个hnsw类型的索引:

from pymilvus import (
    connections,
    Collection,
)

collection_name = "hello_milvus"
host = "192.168.1.32"
port = 19530
username = ""
password = ""


print("start connecting to Milvus")
connections.connect("default", host=host,port=port,user=username,password=password)
coll = Collection(collection_name, consistency_level="Bounded",shards_num=1)

print("Start creating index")

index_params = {
     "index_type": "HNSW",
     "metric_type": "L2",
     "params": {
         "M": 16,
         "efConstruction": 60
     }
}
coll.create_index(
    field_name="embedding",
    index_params=index_params,
    index_name="idx_em"
)

print("done")

在这里插入图片描述
刷新
在这里插入图片描述
创建成功,并点击加载
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

六、索引-FLAT索引【程序员猫爪】

1、通过Attu来创建

暴力搜索。召回率100%。

对于需要完美精度并依赖于相对较小(百万级)数据集的向量相似性搜索应用程序,FLAT索引是一个不错的选
择。FLAT不压缩向量,是唯一能保证精确搜索结果的索引。

FLAT是准确的,因为它采用穷尽的搜索方法,这意味着对于每个查询,目标输入都会与数据集中的每组向量进行
比较。这使得FLAT成为我们列表中最慢的索引,并且不太适合查询大量向量数据。Milvus中FLAT索引不需要
任何参数,使用它不需要数据训练。

创建其它索引需要耗费一定时间,FLAT是瞬间完成。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2、通过pymilvus来创建

在这里插入图片描述
运行下面的代码,

from pymilvus import (
    connections,Collection
)

collection_name = "hello_milvus"
host = "192.168.1.32"  # 替换为你的 Milvus 服务器 IP 地址
port = "19530"  # Milvus 服务端口
username = ""  # 如果需要认证,提供用户名
password = ""  # 如果需要认证,提供密码

print("start connecting to Milvus")
connections.connect("default", host=host, port=port, user=username, password=password)
coll = Collection(collection_name, consistency_level="Bounded",shards_num=1)

print("Start creating index")
index_params = {
    "index_type": "FLAT",
    "metric_type": "L2",
    "params": {}
}
coll.create_index(
    field_name="embedding",
    index_params=index_params,
    index_name="idx_em"
)

print("done")

coll.load()

在这里插入图片描述
在这里插入图片描述

七、对元数据进行解析【程序员猫爪】

在这之前我们吧上面的Collection删除,创建一个新的Collection
在这里插入图片描述
在这里插入图片描述

创建好对应的字段和索引
在这里插入图片描述
在这里插入图片描述
下载:etcdmanager
在这里插入图片描述

下载:https://github.com/gtamas/etcdmanager/releases/download/1.2.0/etcd-manager-1.2.0-win64.exe

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
上面的数据是乱码的,需要下面这个工具进行反序列化

下载对应的工具:https://github.com/melodyfx/milvusmetagui/releases/download/v1.2/milvusmetagui_v1.2.zip
在这里插入图片描述
1.解析database
通过etcd-manager工具搜索database/db-info可以列出milvus中的数据库。
在这里插入图片描述
取其中一个,例如by-dev/meta/root-coord/database/db-info/1
在这里插入图片描述
2.解析collection
通过etcd-manager工具搜索database/collection-info可以列出milvus中的collection。
在这里插入图片描述
取其中一个,例如by-dev/meta/root-coord/database/collection-info/1/449952137045880999

在这里插入图片描述
3.解析fields
通过etcd-manager工具搜索root-coord/fields可以列出milvus中的field。
在这里插入图片描述
取其中一个,例如by-dev/meta/root-coord/fields/449952137045880999/102
在这里插入图片描述
4.解析field-index
通过etcd-manager工具搜索field-index可以列出milvus中的field-index。
在这里插入图片描述
取其中一个,例如by-dev/meta/field-index/449952137045880999/449952137045881004
在这里插入图片描述
5.解析segment-index
通过etcd-manager工具搜索segment-index可以列出milvus中的segment-index。
在这里插入图片描述
取其中一个,例如by-dev/meta/segment-index/449952137045880999/449952137045881000/449952137046086601/449952137047289214
在这里插入图片描述
6.解析partition
通过etcd-manager工具搜索root-coord/partitions可以列出milvus中的partition。
在这里插入图片描述
取其中一个,例如by-dev/meta/segment-index/449952137045880999/449952137045881000/449952137046086601/449952137047289214
在这里插入图片描述

八、milvus元数据存储规则【程序员猫爪】

1、创建新的索引,并添加一部分数据

import uuid
import numpy as np
from pymilvus import (
    connections,
    FieldSchema, CollectionSchema, DataType,
    Collection,
)

collection_name = "hello_milvus"
host = "192.168.1.32"
port = 19530
username = ""
password = ""

num_entities, dim = 3000, 128

def generate_uuids(number_of_uuids):
    uuids = [str(uuid.uuid4()) for _ in range(number_of_uuids)]
    return uuids

print("start connecting to Milvus")
connections.connect("default", host=host, port=port, user=username, password=password)

fields = [
    FieldSchema(name="pk", dtype=DataType.INT64, is_primary=True, auto_id=False),
    FieldSchema(name="random", dtype=DataType.DOUBLE),
    FieldSchema(name="comment", dtype=DataType.VARCHAR, max_length=200),
    FieldSchema(name="embeddings", dtype=DataType.FLOAT_VECTOR, dim=dim)
]

schema = CollectionSchema(fields, description="hello_milvus is the simplest demo to introduce the APIs")

print("Create collection 'hello_world'")
coll = Collection(collection_name, schema, consistency_level="Bounded", shards_num=1)

print("Start inserting entities")
rng = np.random.default_rng(seed=19530)
entities = [
    [i for i in range(num_entities)],
    rng.random(num_entities).tolist(),
    generate_uuids(num_entities),
    rng.random((num_entities, dim)),
]

insert_result = coll.insert(entities)

print("Start flush")
coll.flush()

index_params = {
    "index_type": "HNSW",
    "metric_type": "COSINE",
    "params": {"M": 16, "efConstruction": 100}
}

coll.create_index(
    field_name="embeddings",
    index_params=index_params,
    index_name="idx_em"
)

coll.load()
print("done")

在这里插入图片描述
创建成功
在这里插入图片描述
在这里插入图片描述

2、milvus元数据在etcd的存储解析

数据以key-value形式存在。

大致包含如下一些种类:

database
collection
field
partition
index
segment-index
resource_group
session

database

创建一个数据库会产生2个key,但value是相同的。

key规则:

前缀/root-coord/database/db-info/{dbID}

前缀/snapshots/root-coord/database/db-info/{dbID}_ts{时间戳}

解析一下:database/db-info
默认数据库名为default,dbID为1。

ID和时间戳都是一串数字,由physicalTime+logicalTime组成。

产生的2个key如下:

by-dev/meta/root-coord/database/db-info/1

by-dev/meta/snapshots/root-coord/database/db-info/1_ts455190285690077185

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

collection

创建一个collection会产生2个key,但value是相同的。

key规则:

前缀/root-coord/database/collection-info/{dbID}/{collectionID}

前缀/snapshots/root-coord/database/collection-info/{dbID}/{collectionID}_ts{时间戳}

可以反映出collection属于哪个DB。

collection,产生如下2个key:

by-dev/meta/root-coord/database/collection-info/1/455190360914921460

by-dev/meta/snapshots/root-coord/database/collection-info/1/455190360914921460_ts455190475339988999

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

field

创建collection的时候会创建field,一个field会产生2个key,但value是相同的。

key规则:

前缀/root-coord/fields/{collectionID}/{fieldID}

前缀/snapshots/root-coord/fields/{collectionID}/{fieldID}_ts{时间戳}

可以反映field属于哪个collection。虽然并未反应出属于哪个db,但是collectionID是唯一的,也可以通过collectionID判断出属于那个db。这样不同的db下面有相同名称的collection就可以区别了。

一个field就是一个字段。

创建一个名为testcol01的collection,包含2个field(hid和embedding)产生的key如下:

hid字段:
by-dev/meta/root-coord/fields/444384207423938951/100

by-dev/meta/snapshots/root-coord/fields/444384207423938951/100_ts444384154740064260
embedding字段:
by-dev/meta/root-coord/fields/444384207423938951/101

by-dev/meta/snapshots/root-coord/fields/444384207423938951/101_ts444384154740064260

value结构如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

partition

在这里插入图片描述
创建一个分区会产生2个key,但value是相同的。

key规则:

前缀/root-coord/partitions/{collectionID}/{partitionID}

前缀/snapshots/root-coord/partitions/{collectionID}/{partitionID}_ts{时间戳}

可以反映partition属于哪个collection。

一个collection可以包含多个partition。

默认partition名为:_default。

可配置(milvus.yml):common.defaultPartitionName

在名为testcol01的collection下包含1个partition,产生如下2个key:

by-dev/meta/root-coord/partitions/444384963133177989/444384963133177990

by-dev/meta/snapshots/root-coord/partitions/444384963133177989/444384963133177990_ts444384154740064260

value结构如下:
在这里插入图片描述
在这里插入图片描述
将此结构体序列化后存入到etcd,因此etcd存储的是二进制数据。

index

创建index会产生2个类型的key。一个是index,一个是segment-index。

key规则:

前缀/field-index/{collectionID}/{IndexID}
可以反映index属于哪个collection。Index的value可以反映索引建立在哪个field。

不能反映属于哪个partition、哪个segment。

创建一个名为idx_embedding的索引,产生1个类型的key如下:

by-dev/meta/field-index/444384207423931210/444425876914135276
value结构如下:
在这里插入图片描述
在这里插入图片描述
将此结构体序列化后存入到etcd,因此etcd存储的是二进制数据。

segment-index

创建index会产生2个类型的key。一个是index,一个是segment-index。

key规则:

前缀/segment-index/{collectionID}/{partitionID}/{segmentID}/{buildID}
创建一个名为idx_embedding的索引,产生1个类型的key如下:

by-dev/meta/segment-index/444517122896489678/444517122896489679/444517122896489694/444521062292259541
value结构如下:
在这里插入图片描述
在这里插入图片描述
将此结构体序列化后存入到etcd,因此etcd存储的是二进制数据。

resource_group

资源组可以用来进行查询节点的物理隔离。

在多collection环境中,为每个资源组分配适当数量的查询节点,应用到collection中

key规则:

前缀/queryCoord-ResourceGroup/{rgName}
创建一个名为rg的资源组,产生如下1个key:

by-dev/meta/queryCoord-ResourceGroup/rg
value结构如下:
在这里插入图片描述
将此结构体序列化后存入到etcd,因此etcd存储的是二进制数据。

3、milvus的向量数据和索引数据在s3的存储

查看容器

docker ps

在这里插入图片描述

docker exec -it milvus-standalone bash

在这里插入图片描述
查看对应的配置文件

cd /milvus/configs

将对应的配置文件从docker导出到本机,

exit
docker cp milvus-standalone:/milvus/configs/milvus.yaml .

在这里插入图片描述
我们可以看到一些配置信息
在这里插入图片描述
http://localhost:9001/login
在这里插入图片描述

用户名:minioadmin
密码:minioadmin

配置文件与之对应

在这里插入图片描述

data在s3的存储

对于向量数据(vector data)和索引数据(index data)在 S3 上的存储,Milvus 一般遵循以下模式:

  1. 向量数据 (Vector Data):
    • 向量数据是实际的嵌入式数据点,这些数据点可以来自于图像、文本、音频等。
    • 在 S3 中,向量数据可能会被分片(sharded)存储以提高读写性能,并且每个分片可能会有一个唯一的标识符。
    • 存储路径可能类似于:s3://<bucket-name>/collections/<collection-name>/segments/<segment-id>/vectors/
  2. 索引数据 (Index Data):
    • 索引数据是为了加速查询而构建的数据结构,如倒排索引、树形结构或其他类型的近似最近邻(ANN)索引。
    • 索引文件同样会被分片并分布在多个S3对象中。
    • 存储路径可能类似于:s3://<bucket-name>/collections/<collection-name>/indexes/<index-type>/<index-id>/
  3. Collections:
    • Collections 是 Milvus 数据库中的顶层容器,每个 Collection 可以包含多个字段,包括主键和一个或多个向量字段。
    • 在 S3 上,Collection 的元数据和其关联的向量及索引数据都存放在特定的目录下。
    • 存储路径可能类似于:s3://<bucket-name>/collections/<collection-name>/
      向量数据在s3的存储路径:

格式:
在这里插入图片描述
在这里插入图片描述

一个partition包含多个segments。
例子:
在这里插入图片描述

index在s3的存储

索引数据在s3的存储:
以HNSW索引类型为例。

格式:

files/index_files/{buildID}/{indexVersion}/{partitionID}/{segmentID}/文件

例子:

files/index_files/444545479156434329/1/444517122896489679/44451712896489694/HNSW

九、架构和组件介绍【程序员猫爪】

Milvus 采用共享存储架构,具有存储和计算分离的特点,计算节点具有水平可扩展性。遵循数据平面和控制平面
分离的原则,Milvus包含四层:访问层、协调器服务、工作节点和存储,这些层是相互独立的。
在这里插入图片描述

接入层

接入层由一组无状态代理组成,是系统的最前端,也是用户的终端,负责验证客户端请求,并返回结果:

  • Proxy本身是无状态的

  • 由于Milvus采用大规模并行处理(MPP)架构,proxy会聚合结果,然后再将最终结果返回给客户端。

协调器服务

协调器服务负责将任务分配给工作节点,充当系统的大脑。它承担的任务包括集群拓扑管理、负载均衡、时间戳生
成、数据声明和数据管理。
协调器类型有三种:

  • 根协调器(rootcoord)
  • 数据协调器(datacoord, indexcoord)
  • 查询协调器(querycoord)

根协调器 (RootCoord)

职责:

  • DDL 和 DCL 请求处理: 负责处理所有与数据定义语言(DDL)和数据控制语言(DCL)相关的请求,包括创建、修改或删除集合(Collections)、分区(Partitions)、索引等。
  • TSO 管理: 维护时间戳预言机(Timestamp Oracle),用于生成全局唯一的时间戳,确保分布式事务的一致性。
  • 计时器发放: 分配和管理定时任务,这可能涉及到周期性的维护操作或者触发某些后台进程。

查询协调器 (QueryCoord)

职责:

  • 查询节点管理: 监控和管理查询节点的状态,确保查询能够被有效地分发到合适的节点上执行。
  • 负载均衡: 实现查询请求的负载均衡,优化资源利用,避免某些节点过载。
  • 段状态转换: 处理从增长段到密封段的状态转换,确保数据在适当的时候从写入状态切换到只读状态,以供查询使用。

数据协调器 (DataCoord)

职责:

  • 数据节点管理: 管理数据节点之间的拓扑结构,确保数据分布合理,以及数据复制和迁移。
  • 索引节点管理: 类似地,也管理索引节点,保证索引数据的高效存储和检索。
  • 元数据维护: 维护关于数据和索引的元数据,如位置、大小、版本等信息。
  • 后台任务触发: 触发诸如flush(将内存中的数据刷入磁盘)、compaction(压缩)、索引构建等后台任务,以保持系统的高性能和一致性。

工作节点

工作节点是无状态的。

工作节点是执行器,它们遵循协调器服务的指令并执行来自proxy的数据操作语言(DML)命令。

工作节点有三种类型:

查询节点(querynode)

查询节点通过订阅log broker来获取增量日志数据并将其转换为增长段,从对象存储中加载历史数据,并在向量数
据和标量数据之间进行混合搜索。

数据节点(datanode)

数据节点通过订阅log broker来获取增量日志数据,处理mutation请求,并将日志数据打包成日志快照并存储在
对象存储中。

索引节点(indexnode)

索引节点负责构建索引,索引节点不需要常驻内存,可以使用serverless框架实现。

存储

存储负责数据的持久化,包括元存储、日志代理、对象存储。

元存储

元存储用于存储元数据的快照,例如集合schema和消息消费检查点。存储元数据需要极高的可用性、强一致性和
事务支持,因此Milvus选择etcd作为元存储。Milvus还使用etcd进行服务注册和健康检查。

对象存储

对象存储主要存储日志的快照文件、标量和向量数据的索引文件以及查询的中间结果。Milvus使用MinlO作为对
象存储。

日志代理

日志代理是一个支持回放的发布-订阅系统。它负责流数据持久化和事件通知。它还确保当工作节点从系统故障中
恢复时增量数据的完整性。Milvus集群使用Pulsar作为日志代理;Milvus standalone使用RocksDB作为日志代
理。

十、Milvus的管理和使用【数据库管理】【程序员猫爪】

1、管理数据库

与传统数据库引擎类似,您也可以在Milvus中创建数据库。
使用逻辑来看看需要什么样的API。
创建、删除
use、列出

2、创建数据库

from pymilvus import (
    connections, db
)

collection_name = "hello_milvus"
host = "192.168.1.31"
port = 19530
username = ""
password = ""

print("start connecting to Milvus")
connections. connect("default", host=host, port=port, user=username, password=password)

#创建数据库
database = db.create_database("book")

print("done")

在这里插入图片描述

3、使用数据库

db.using_database('book')

或者

conn = connections.connect(
	host="127.0.0.1",
	port="19530",
	db_name="book"
}

4、列出数据库

print(db.list_database())

在这里插入图片描述

5、删除数据库

db.drop_database("book")

十一、collection操作【程序员猫爪】

1、创建collection

from pymilvus import (
    connections,
    FieldSchema, CollectionSchema, DataType,
    Collection,
)

collection_name = "hello_milvus"
host = "192.168.0.101"
port = 19530
username = ""
password = ""
num_entities, dim = 5000, 3

print("start connecting to Milvus")
connections.connect("default", host=host, port=port, user=username, password=password)

fields = [
    FieldSchema(name="pk", dtype=DataType.INT64, is_primary=True, auto_id=False),
    FieldSchema(name="random", dtype=DataType.DOUBLE),
    FieldSchema(name="comment", dtype=DataType.VARCHAR, max_length=200),
    FieldSchema(name="embeddings", dtype=DataType.FLOAT_VECTOR, dim=dim)
]

schema = CollectionSchema(fields, description="hello_milvus is the simplest demo to introduce the APIs")

print("Create collection 'hello_world'")
coll = Collection(collection_name, schema, consistency_level="Bounded", shards_num=1)

print("done")

在这里插入图片描述
刷新页面看到已经创建成功
在这里插入图片描述

2、删除collection

coll.drop()

函数定义:

def drop(self, timeout: Optional[float] = None, ** kwargs):

有一个timeout参数。

3、加载collection

功能:加载collection到内存

coll.load()
def load(
	self,
	partition_names: Optional[list] = None,
	replica_number: int = 1,
	timeout: Optional[float] = None,
	** kwargs,
)

在这里插入图片描述
在这里插入图片描述
创建好索引以后可以通过上面的代码加载对应的内容

coll.load() #
coll.load(_async=True)
utility.wait_for_loading_complete("hello_iterator")

4、释放collection

从内存中卸载。

coll.release()

5、描述collection

获取collection的信息

infos = coll. describe()

十二、向量搜索search【程序员猫爪】

插入数据后,下一步是在Milvus中对collection执行相似性搜索。

有两种类型的搜索

  • 单向量搜索

collection中只有一个向量字段,使用search()方法。

  • 多向量搜索

collection有两个或多个向量字段,使用hybrid_search()方法,此方法执行多个近似最近邻(ANN)搜索请求,合并结果,重新排
序,返回最相关的匹配项。

有多种搜索类型可满足不同的需求:

  • 基本搜索:包括单向量搜索、批量向量搜索、分区搜索、指定输出字段的搜索。

  • 过滤搜索:应用基于标量字段的过滤条件来优化搜索结果。

  • 范围搜索:查找距离查询向量特定距离范围内的向量。

  • 分组搜索:根据特定字段对搜索结果进行分组,以确保结果的多样性。

单向量搜索:

准备测试数据:

为了方便观察,dim维度设置为3。

1、插入数据

import uuid

import numpy as np
from pymilvus import (
    connections,
    FieldSchema, CollectionSchema, DataType,
    Collection,
)

# 定义要操作的集合名称、服务器地址和端口
collection_name = "hello_milvus"
host = "192.168.1.32"
port = 19530
username = ""  # 如果需要认证,则提供用户名
password = ""  # 如果需要认证,则提供密码
num_entities, dim = 3000, 3  # 定义将插入实体的数量和嵌入维度

def generate_uuids(number_of_uuids):
    # 生成指定数量的UUID字符串列表
    uuids = [str(uuid.uuid4()) for _ in range(number_of_uuids)]
    return uuids

print("start connecting to Milvus")
# 建立到Milvus服务的连接
connections.connect("default", host=host, port=port, user=username, password=password)

fields = [
    # 定义字段模式:主键(整数类型)、随机值(浮点类型)、评论(可变字符类型)以及嵌入(浮点向量)
    FieldSchema(name="pk", dtype=DataType.INT64, is_primary=True, auto_id=False),
    FieldSchema(name="random", dtype=DataType.DOUBLE),
    FieldSchema(name="comment", dtype=DataType.VARCHAR, max_length=200),
    FieldSchema(name="embeddings", dtype=DataType.FLOAT_VECTOR, dim=dim)
]

# 创建集合模式,包括字段定义和描述信息
schema = CollectionSchema(fields, "hello_milvus is the simplest demo to introduce the APIs")

print("Create collection `hello_world`")
# 根据模式创建集合,并设置一致性级别为有界(Bounded)和分片数量为1
coll = Collection(collection_name, schema, consistency_level="Bounded", shards_num=1)

print("Start inserting entities")
rng = np.random.default_rng(seed=19530)  # 使用固定种子初始化随机数生成器以保证结果可重复
entities = [
    [i for i in range(num_entities)],  # 主键字段,从0开始的整数序列
    rng.random(num_entities).tolist(),  # 随机值字段,生成num_entities个随机浮点数
    generate_uuids(num_entities),       # 评论字段,生成num_entities个随机UUID作为文本数据
    rng.random((num_entities, dim)),    # 嵌入字段,生成num_entities个dim维的随机向量
]

# 插入实体到集合中
insert_result = coll.insert(entities)

print("Start flush")
# 强制刷新集合,确保所有数据都被写入磁盘
coll.flush()

print("Start creating index")
index_params = {
    "index_type": "HNSW",           # 指定索引类型为Hierarchical Navigable Small World graph
    "metric_type": "COSINE",        # 指定度量类型为余弦距离
    "params": {
        "M": 16,                    # HNSW参数M
        "efConstruction": 40        # HNSW参数efConstruction
    }
}

# 在嵌入字段上创建索引
coll.create_index(
    field_name="embeddings",
    index_params=index_params,
    index_name="idx_em"
)

# 加载集合到内存中,以便能够进行搜索等操作
coll.load()

print("done")

在运行上述代码之前删除对应的collections
在这里插入图片描述
运行代码
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
[0.20963513851165771,0.3974665701389313,0.12019053101539612]

2、向量搜索

import random
# 导入pymilvus库中的相关模块,用于与Milvus数据库交互
from pymilvus import (
    connections,  # 用于管理到Milvus服务的连接
    Collection,   # 用于操作集合(类似于数据库中的表)
)

dim = 3  # 定义嵌入向量的维度

if __name__ == '__main__':
    # 当该文件作为主程序运行时执行以下代码块

    # 建立到Milvus服务器的连接
    connections.connect(
        alias="default",  # 连接别名,默认为"default"
        user='',          # 如果需要认证,请提供用户名
        password='',      # 如果需要认证,请提供密码
        host='192.168.1.32',  # Milvus服务器的IP地址或主机名
        port='19530'      # Milvus服务器监听的端口号
    )

    # 获取名为"hello_milvus"的集合对象,如果集合不存在则会抛出异常
    coll = Collection("hello_milvus")

    # 定义搜索参数,包括使用的度量类型和索引参数
    search_param = {
        "metric_type": "COSINE",  # 使用余弦相似度作为度量标准
        "params": {"ef": 40}      # 索引参数,这里指的是HNSW索引的探索因子
    }

    # 生成一个随机的查询向量,长度为dim
    search_data = [random.random() for _ in range(dim)]

    # 执行搜索操作,在集合中查找与search_data最相似的实体
    results = coll.search(
        data=[search_data],  # 查询向量列表
        anns_field="embeddings",  # 指定进行相似性搜索的字段名称
        param=search_param,       # 搜索参数
        limit=5,                  # 返回的结果数量限制
        output_fields=['pk', 'embeddings']  # 输出结果中包含的字段
    )

    # 打印搜索结果
    print(results)

在这里插入图片描述
在这里插入图片描述

运行上述代码
在这里插入图片描述

data: ['["id: 629, distance: 0.9999996423721313, entity: {\'embeddings\': [0.19573082029819489, 
0.5741711258888245, 0.8462685346603394], \'pk\': 629}", "id: 474, distance: 0.9999852776527405, entity: 
{\'embeddings\': [0.1356295943260193, 0.3976878523826599, 0.5801228284835815], \'pk\': 474}", "id: 2892, 
distance: 0.9999129772186279, entity: {\'embeddings\': [0.15993863344192505, 0.45773211121559143, 
0.6593530774116516], \'pk\': 2892}", "id: 2685, distance: 0.9996669292449951, entity: {\'embeddings\': 
[0.1625087559223175, 0.5192853808403015, 0.7944508194923401], \'pk\': 2685}", "id: 203, distance: 
0.9995291233062744, entity: {\'embeddings\': [0.10804865509271622, 0.28262680768966675, 0.40316230058670044], 
\'pk\': 203}"]']

十三、批量向量搜索【程序员猫爪】

批量向量搜索允许在单个请求中进行多个向量相似性搜索。这种类型的搜索非常适合需要为一组查询向量查找相似向量的场景,可显著减
少所需的时间和计算资源。

即:一次查询多个向量,吞吐。

系统会并行处理这些向量,为每个查询向量返回一个单独的结果集,每个结果集包含在collection中找到的最接近的匹配项。

import random
# 导入pymilvus库中的相关模块,用于与Milvus数据库交互
from pymilvus import (
    connections,  # 用于管理到Milvus服务的连接
    Collection,   # 用于操作集合(类似于数据库中的表)
)

dim = 3  # 定义嵌入向量的维度

if __name__ == '__main__':
    # 当该文件作为主程序运行时执行以下代码块

    # 建立到Milvus服务器的连接
    connections.connect(
        alias="default",  # 连接别名,默认为"default"
        user='',          # 如果需要认证,请提供用户名
        password='',      # 如果需要认证,请提供密码
        host='192.168.1.32',  # Milvus服务器的IP地址或主机名
        port='19530'      # Milvus服务器监听的端口号
    )

    # 获取名为"hello_milvus"的集合对象,如果集合不存在则会抛出异常
    coll = Collection("hello_milvus")

    # 定义搜索参数,包括使用的度量类型和索引参数
    search_param = {
        "metric_type": "COSINE",  # 使用余弦相似度作为度量标准
        "params": {"ef": 40}      # 索引参数,这里指的是HNSW索引的探索因子
    }

    # 定义查询向量列表,每个向量长度为dim
    search_data = [
        [0.20963513851165771, 0.3974665701389313, 0.12019053101539612],
        [0.6947491765022278, 0.9535574913024902, 0.5454552173614502]
    ]

    # 执行搜索操作,在集合中查找与search_data最相似的实体
    results = coll.search(
        data=search_data,         # 查询向量列表
        anns_field="embeddings", # 指定进行相似性搜索的字段名称
        param=search_param,       # 搜索参数
        limit=5,                  # 返回的结果数量限制
        output_fields=['pk'],     # 输出结果中包含的字段,这里是主键
        # consistency_level="Eventually"  # 可选的一致性级别设置
    )

    # 打印搜索结果
    print(results)
data: ['["id: 0, distance: 0.9999999403953552, entity: {\'pk\': 0}", "id: 2971, distance: 0.9999716877937317, 
entity: {\'pk\': 2971}", "id: 2813, distance: 0.9999514222145081, entity: {\'pk\': 2813}", "id: 1828, distance: 
0.9999250173568726, entity: {\'pk\': 1828}", "id: 788, distance: 0.9998787641525269, entity: {\'pk\': 788}"]', 
'["id: 1, distance: 1.0, entity: {\'pk\': 1}", "id: 1707, distance: 0.999962329864502, entity: {\'pk\': 1707}", 
"id: 1360, distance: 0.999888002872467, entity: {\'pk\': 1360}", "id: 113, distance: 0.9998663067817688, 
entity: {\'pk\': 113}", "id: 146, distance: 0.9998223781585693, entity: {\'pk\': 146}"]']

Process finished with exit code 0

十四、分区搜索【程序员猫爪】

1.创建分区blue、red
2.向分区插入数据

# 导入所需的库和模块
import uuid
import numpy as np
from pymilvus import (
    connections,  # Milvus连接管理器
    FieldSchema, CollectionSchema, DataType,  # 定义集合模式所需类
    Collection,  # 用于操作Milvus中的集合
)

# 设置集合名称、服务器地址和端口,以及认证信息(如果需要)
collection_name = "hello_milvus"
host = "192.168.1.32"  # Milvus服务器IP地址
port = 19530  # Milvus服务器端口号
username = ""  # 用户名,可为空
password = ""  # 密码,可为空
num_entities, dim = 3000, 3  # 定义实体数量和向量维度

def generate_uuids(number_of_uuids):
    """生成指定数量的UUID列表"""
    uuids = [str(uuid.uuid4()) for _ in range(number_of_uuids)]
    return uuids

print("start connecting to Milvus")
# 建立到Milvus服务器的连接
connections.connect(
    alias="default",  # 连接别名
    host=host,
    port=port,
    user=username,
    password=password
)

# 定义集合中的字段,包括主键、随机数、注释和嵌入向量
fields = [
    FieldSchema(name="pk", dtype=DataType.INT64, is_primary=True, auto_id=False),  # 主键字段
    FieldSchema(name="random", dtype=DataType.DOUBLE),  # 随机数字段
    FieldSchema(name="comment", dtype=DataType.VARCHAR, max_length=200),  # 注释字段,最大长度200字符
    FieldSchema(name="embeddings", dtype=DataType.FLOAT_VECTOR, dim=dim)  # 向量字段,维数为dim
]

# 创建集合模式,并附加描述性文本
schema = CollectionSchema(fields, "hello_milvus is the simplest demo to introduce the APIs")

print("Create collection `hello_world`")  # 注意:这里可能是笔误,应该是创建名为 `hello_milvus` 的集合
# 根据定义的模式创建一个新集合
coll = Collection(collection_name, schema, consistency_level="Bounded", shards_num=1)

print("Create partition `blue` and `red`")
# 在集合中创建两个分区,用于组织数据
coll.create_partition(partition_name="blue")
coll.create_partition(partition_name="red")

print("Start inserting entities")
# 使用numpy随机数生成器初始化随机数种子
rng = np.random.default_rng(seed=19530)
# 插入第一组实体到'blue'分区
entities1 = [
    [i for i in range(num_entities)],  # 主键值
    rng.random(num_entities).tolist(),  # 随机数值
    generate_uuids(num_entities),  # 生成的UUID作为注释
    rng.random((num_entities, dim)),  # 随机生成的嵌入向量
]
coll.insert(data=entities1, partition_name="blue")

# 插入第二组实体到'red'分区
entities2 = [
    [i + 3000 for i in range(num_entities)],  # 主键值从3000开始
    rng.random(num_entities).tolist(),
    generate_uuids(num_entities),
    rng.random((num_entities, dim)),
]
coll.insert(data=entities2, partition_name="red")

print("Start flush")
# 确保所有插入的数据都已经被写入磁盘
coll.flush()

print("Start creating index")
# 定义索引参数,使用HNSW算法进行高效近似最近邻搜索
index_params = {
    "index_type": "HNSW",
    "metric_type": "L2",  # L2距离度量
    "params": {
        "M": 16,  # HNSW图的最大连接数
        "efConstruction": 40  # 构建索引时的探索因子
    }
}

# 在'embeddings'字段上创建索引
coll.create_index(
    field_name="embeddings",
    index_params=index_params,
    index_name="idx_em"
)

# 加载集合到内存,使其可以被查询
coll.load()
print("done")

在运行上述代码之前将之前创建的collections删除
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
指定分区进行搜索:

搜索结果将被限制在指定的分区内。

import random  # 导入用于生成随机数的模块(此脚本中未使用)
from pymilvus import (  # 导入与Milvus数据库交互所需的类
    connections,  # 用于连接到Milvus服务器
    Collection,  # 用于表示数据库中的集合(类似于表格)
)

if __name__ == '__main__':
    # 如果这个文件作为主程序运行,则执行以下代码块

    # 建立与Milvus数据库的连接。需要提供连接别名、用户名、密码、主机IP和端口。
    connections.connect(
        alias="default",  # 连接的别名,默认即可
        user='',  # 用户名,如果不需要认证可以留空
        password='',  # 密码,同上
        host='192.168.1.32',  # Milvus服务器的IP地址
        port='19530'  # Milvus服务监听的端口号
    )

    # 创建一个指向名为 "hello_milvus" 的集合的引用。该集合必须事先存在于Milvus中。
    coll = Collection("hello_milvus")

    # 定义搜索参数,包括距离度量类型(metric_type)和索引搜索参数(params)
    search_param = {
        "metric_type": "L2",  # 使用欧几里得距离(L2范数)来计算向量之间的相似度
        "params": {"ef": 40}  # 索引参数,具体取决于所使用的索引类型;这里的ef是HNSW索引的一个参数
    }

    # 定义要搜索的数据点,这是一个包含单个向量的列表,该向量有三个浮点数值
    search_data = [[0.20963513851165771, 0.3974665701389313, 0.12019053101539612]]

    # 执行搜索操作,并获取结果
    results = coll.search(
        data=search_data,  # 要查询的数据向量
        anns_field="embeddings",  # 集合中存储嵌入向量的字段名
        param=search_param,  # 搜索参数,定义了如何评估相似度
        partition_names=["blue"],  # 可选参数,指定在哪些分区内进行搜索
        limit=5,  # 返回的最相似项的数量
        output_fields=['pk'],  # 返回结果中除了距离外还包含的字段
    )

    # 输出搜索结果
    print(results)  # 将搜索结果打印到控制台

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/957548.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

第35天:安全开发-JavaEE应用原生反序列化重写方法链条分析触发类类加载

时间轴&#xff1a; 序列化与反序列化图解&#xff1a; 演示案例&#xff1a; Java-原生使用-序列化&反序列化 Java-安全问题-重写方法&触发方法 Java-安全问题-可控其他类重写方法 Java-原生使用-序列化&反序列化 1.为什么进行序列化和反序列化&#xff1…

Python----Python高级(文件操作open,os模块对于文件操作,shutil模块 )

一、文件处理 1.1、文件操作的重要性和应用场景 1.1.1、重要性 数据持久化&#xff1a; 文件是存储数据的一种非常基本且重要的方式。通过文件&#xff0c;我们可 以将程序运行时产生的数据永久保存下来&#xff0c;以便将来使用。 跨平台兼容性&#xff1a; 文件是一种通用…

[MCAL]Mcu配置

PostBuild: PreCompile: 选择时钟来源&#xff1b; 选择初始McuInitClock() 函数 电路手册里有晶振频率&#xff0c;如上所示&#xff1b;

(k8s)k8s部署mysql与redis(无坑版)

0.准备工作 在开始之前&#xff0c;要确保我们的节点已经加入网络并且已经准备好&#xff0c;如果没有可以去看我前面发表的踩坑与解决的文章&#xff0c;希望能够帮到你。 1.k8s部署redis 1.1目标 由于我们的服务器资源较小&#xff0c;所以决定只部署一个redis副本&#x…

Python新春烟花

目录 系列文章 写在前面 技术需求 完整代码 下载代码 代码分析 1. 程序初始化与显示设置 2. 烟花类 (Firework) 3. 粒子类 (Particle) 4. 痕迹类 (Trail) 5. 烟花更新与显示 6. 主函数 (fire) 7. 游戏循环 8. 总结 注意事项 写在后面 系列文章 序号直达链接爱…

机器学习09-Pytorch功能拆解

机器学习09-Pytorch功能拆解 我个人是Java程序员&#xff0c;关于Python代码的使用过程中的相关代码事项&#xff0c;在此进行记录 文章目录 机器学习09-Pytorch功能拆解1-核心逻辑脉络2-个人备注3-Pytorch软件包拆解1-Python有参和无参构造构造方法的基本语法示例解释注意事项…

AI在SEO中的关键词优化策略探讨

内容概要 在当今数字化时代&#xff0c;人工智能&#xff08;AI&#xff09;正逐渐重塑搜索引擎优化&#xff08;SEO&#xff09;行业。AI技术的快速发展使得SEO策略发生了翻天覆地的变化&#xff0c;特别是在关键词优化方面。关键词优化的基本概念是通过选择与用户搜索意图密…

探索与创作:2024年我在CSDN平台上的成长与突破

文章目录 我与CSDN的初次邂逅初学阶段的阅读CSDN&#xff1a;编程新手的避风港初学者的福音&#xff1a;细致入微的知识讲解考试复习神器&#xff1a;技术总结的“救命指南”曾经的自己&#xff1a;为何迟迟不迈出写博客的第一步兴趣萌芽&#xff1a;从“读”到“想写”的初体验…

element el-table合并单元格

合并 表格el-table添加方法:span-method"” <el-table v-loading"listLoading" :data"SHlist" ref"tableList" element-loading-text"Loading" border fit highlight-current-row :header-cell-style"headClass" …

行业热点丨低空飞行eVTOL的关键技术与发展趋势

本篇主要围绕eVTOL仿真难点和趋势&#xff0c;eVTOL仿真多学科解决方案和当下热门的AI或者机器学习的方法在EVTOL中的应用展开。 eVTOL 研发难点 首先是eVTOL研发难点&#xff0c;区别于上个世纪70年代就已经构型稳定或者技术方法稳定的民航客机&#xff0c;eVTOL到今天尚未有经…

BOBO小火炬全套源码XE修复版2025(火炬天花板二次开发版)

《小火炬全套源码 传奇游戏源码讲解》 小火炬全套源码是一种用于开发经典传奇类游戏的源码包。传奇游戏作为一款经典的多人在线角色扮演游戏&#xff08;MMORPG&#xff09;&#xff0c;有着庞大的用户基础和强大的游戏生态。小火炬全套源码主要提供了从基础架构到核心功能的完…

Flutter:搜索页,搜索bar封装

view 使用内置的Chip简化布局 import package:chenyanzhenxuan/common/index.dart; import package:ducafe_ui_core/ducafe_ui_core.dart; import package:flutter/material.dart; import package:get/get.dart; import package:tdesign_flutter/tdesign_flutter.dart;import i…

网络通信---MCU移植LWIP

使用的MCU型号为STM32F429IGT6&#xff0c;PHY为LAN7820A 目标是通过MCU的ETH给LWIP提供输入输出从而实现基本的Ping应答 OK废话不多说我们直接开始 下载源码 LWIP包源码&#xff1a;lwip源码 -在这里下载 ST官方支持的ETH包&#xff1a;ST-ETH支持包 这里下载 创建工程 …

麒麟操作系统服务架构保姆级教程(十三)tomcat环境安装以及LNMT架构

如果你想拥有你从未拥有过的东西&#xff0c;那么你必须去做你从未做过的事情 之前咱们学习了LNMP架构&#xff0c;但是PHP对于技术来说确实是老掉牙了&#xff0c;PHP的市场占有量越来越少了&#xff0c;我认识一个10年的PHP开发工程师&#xff0c;十年工资从15k到今天的6k&am…

elementUI Table组件实现表头吸顶效果

需求描述 当 table 内容过多的时候&#xff0c;页面上滑滚动&#xff0c;表头的信息也会随着被遮挡&#xff0c;无法将表头信息和表格内容对应起来&#xff0c;需要进行表头吸顶 开始编码&#x1f4aa; 环境&#xff1a;vue2.6、element UI step1&#xff1a; 给el-table__h…

AI 新动态:技术突破与应用拓展

目录 一.大语言模型的持续进化 二.AI 在医疗领域的深度应用 疾病诊断 药物研发 三.AI 与自动驾驶的新进展 四.AI 助力环境保护 应对气候变化 能源管理 后记 在当下科技迅猛发展的时代&#xff0c;人工智能&#xff08;AI&#xff09;无疑是最具影响力的领域之一。AI 技…

题解 CodeForces 131D Subway BFS C++

题目传送门 Problem - 131D - Codeforceshttps://codeforces.com/problemset/problem/131/Dhttps://codeforces.com/problemset/problem/131/D 翻译 地铁方案&#xff0c;对于Berland城市来说是一种经典的表示&#xff0c;由一组n站点和连接这些站点的n通道组成&#xff0c;…

如何查看某用户的Git提交数

说明&#xff1a;有些公司自己搭建的Git仓库&#xff0c;可以在仓库项目上查看各用户的提交量及占比。也可通过下面这两个Git命令&#xff0c;查看当前仓库&#xff0c;当前分支的总提交数&#xff0c;及某用户的提交数&#xff1b; # 当前分支的总提交数 git log --oneline |…

SQL sever数据导入导出实验

1.创建数据库TCP-H &#xff08;1&#xff09;右键“数据库”&#xff0c;点击“新建数据库”即可 &#xff08;2&#xff09;用sql语言创建&#xff0c;此处以创建数据库DB_test为例&#xff0c;代码如下&#xff1a; use master;go--检查在当前服务器系统中的所有数据里面…

Codeforces Round 903 (Div. 3) E. Block Sequence

题解&#xff1a; 想到从后向前DP f[i] 表示从 i ~ n 转化为“美观”所需要的最少的步骤 第一种转移方式&#xff1a;直接删除掉第i个元素&#xff0c;那么就是上一步 f[i 1] 加上 1;第二种转移方式&#xff1a;从第 i a[i] 1 个元素直接转移&#xff0c;不需要增加步数&a…