pgvector相似度阈值批量查询并返回top K个结果

前提条件

  1. 确保已安装pgvector扩展。
  2. 确保已在PostgreSQL数据库中创建了带有向量字段的表。

示例

假设有一个包含向量的表items,表结构如下:

CREATE TABLE items (
    id serial PRIMARY KEY,
    vector vector(3)
);

插入样本数据

INSERT INTO items (vector) VALUES
    ('[0.1, 0.2, 0.3]'),
    ('[0.4, 0.5, 0.6]'),
    ('[0.7, 0.8, 0.9]'),
    ('[0.2, 0.1, 0.0]'),
    ('[0.5, 0.4, 0.3]');

查询相似度

假设你有一个查询向量[0.1, 0.2, 0.3],你想从这些样本中找到与其相似的前3个向量,并且设定相似度阈值为0.8。

SELECT id, vector, vector <=> '[0.1, 0.2, 0.3]' AS distance
FROM items
WHERE vector <=> '[0.1, 0.2, 0.3]' < 0.8
ORDER BY vector <=> '[0.1, 0.2, 0.3]'
LIMIT 3;

解释

  1. vector <=> '[0.1, 0.2, 0.3]'计算向量之间的距离。
  2. WHERE vector <=> '[0.1, 0.2, 0.3]' < 0.8过滤出距离小于0.8的向量。
  3. ORDER BY vector <=> '[0.1, 0.2, 0.3]'根据距离从小到大排序。
  4. LIMIT 3限制返回的结果数量为3。

使用Python进行批量查询

如果要用Python进行批量查询,可以使用psycopg2库来执行上述SQL查询:

import psycopg2

def batch_query_similar_vectors(query_vector, threshold, top_k):
    conn = psycopg2.connect(
        dbname="your_database",
        user="your_user",
        password="your_password",
        host="your_host",
        port="your_port"
    )
    cur = conn.cursor()

    query = """
    SELECT id, vector, vector <=> %s AS distance
    FROM items
    WHERE vector <=> %s < %s
    ORDER BY vector <=> %s
    LIMIT %s;
    """

    cur.execute(query, (query_vector, query_vector, threshold, query_vector, top_k))
    results = cur.fetchall()

    cur.close()
    conn.close()

    return results

query_vector = '[0.1, 0.2, 0.3]'
threshold = 0.8
top_k = 3

results = batch_query_similar_vectors(query_vector, threshold, top_k)
for result in results:
    print(result)

这样,你就可以根据相似度阈值批量查询并返回前K个结果。
在pgvector中,向量索引是一种用于加速向量相似度搜索的技术。pgvector支持使用几种不同类型的索引来优化向量查询速度,其中最常见的是IVFFlat索引。以下是关于向量索引的详细介绍:

IVFFlat 索引

IVFFlat (Inverted File with Flat quantization) 是一种常用于向量检索的索引类型,它将向量分成若干簇,并在每个簇内进行快速线性扫描。以下是创建和使用IVFFlat索引的步骤:

创建IVFFlat索引
  1. 创建表格并插入数据:
    首先,创建一个包含向量数据的表格,并插入数据。

    CREATE TABLE items (
        id serial PRIMARY KEY,
        vector vector(3)
    );
    
    INSERT INTO items (vector) VALUES
        ('[0.1, 0.2, 0.3]'),
        ('[0.4, 0.5, 0.6]'),
        ('[0.7, 0.8, 0.9]'),
        ('[0.2, 0.1, 0.0]'),
        ('[0.5, 0.4, 0.3]');
    
  2. 创建IVFFlat索引:
    使用以下SQL命令创建IVFFlat索引。这里的vector_l2_ops表示使用L2距离度量。

    CREATE INDEX ON items USING ivfflat (vector vector_l2_ops) WITH (lists = 100);
    

    在这个命令中,lists参数指定了簇的数量,通常根据数据量和查询性能进行调整。

使用索引进行查询

创建索引后,可以使用向量相似度搜索进行查询。例如,要查找与查询向量[0.1, 0.2, 0.3]相似的前3个结果,可以使用以下查询:

SELECT id, vector, vector <=> '[0.1, 0.2, 0.3]' AS distance
FROM items
ORDER BY vector <=> '[0.1, 0.2, 0.3]'
LIMIT 3;

在有索引的情况下,这个查询会比没有索引的情况快很多,尤其是在数据量较大的情况下。

HNSW 索引

另一种常用的向量索引是HNSW (Hierarchical Navigable Small World)。HNSW索引基于小世界图理论,具有高效的查询性能和构建速度。

创建HNSW索引
CREATE INDEX ON items USING hnsw (vector) WITH (m = 16, ef_construction = 200);

在这个命令中,mef_construction是HNSW算法的参数,分别控制图的稀疏程度和索引构建时的搜索深度。

使用向量索引的好处

  1. 查询速度快: 向量索引显著提高了大规模向量数据的查询速度。
  2. 可扩展性: 支持大规模数据的高效检索。
  3. 灵活性: 支持不同类型的距离度量(如L2距离、内积等)。

索引参数调整

不同的索引类型和参数设置会对性能产生不同影响。根据数据规模和查询需求,可以调整参数(如IVFFlat中的lists或HNSW中的mef_construction)以优化性能。

示例:IVFFlat索引与批量查询

假设你有一个包含5000个向量的查询列表,可以使用创建的IVFFlat索引加速查询:

from concurrent.futures import ThreadPoolExecutor
import psycopg2

def query_similar_vectors_batch(query_vector_batch, threshold, top_k):
    conn = psycopg2.connect(
        dbname="your_database",
        user="your_user",
        password="your_password",
        host="your_host",
        port="your_port"
    )
    cur = conn.cursor()
    
    results = []
    for query_vector in query_vector_batch:
        query = """
        SELECT id, vector, vector <=> %s AS distance
        FROM items
        WHERE vector <=> %s < %s
        ORDER BY vector <=> %s
        LIMIT %s;
        """
        cur.execute(query, (query_vector, query_vector, threshold, query_vector, top_k))
        results.extend(cur.fetchall())

    cur.close()
    conn.close()
    
    return results

def batch_query_similar_vectors(query_vectors, threshold, top_k, batch_size):
    with ThreadPoolExecutor(max_workers=10) as executor:
        futures = [
            executor.submit(query_similar_vectors_batch, query_vectors[i:i + batch_size], threshold, top_k)
            for i in range(0, len(query_vectors), batch_size)
        ]
        results = []
        for future in futures:
            results.extend(future.result())
    return results

query_vectors = [...]  # 5000个长文本向量列表
threshold = 0.8
top_k = 3
batch_size = 500  # 每批次处理500个向量

results = batch_query_similar_vectors(query_vectors, threshold, top_k, batch_size)
for result in results:
    print(result)

通过创建和使用向量索引,可以显著提高pgvector在大规模数据集上的查询性能。

如果优先考虑文本召回率,即希望在相似度查询中尽可能多地召回相关的文本,那么使用HNSW(Hierarchical Navigable Small World)索引通常是一个较好的选择。HNSW索引在保持高查询速度的同时,能够提供较高的召回率。

HNSW索引

HNSW索引基于小世界图理论,通过构建多层图结构,使得在大规模数据集中能够高效地进行近似最近邻搜索。HNSW索引的关键参数有两个:

  1. M: 控制每个节点的最大连接数。较高的值通常会提高召回率,但也会增加索引构建和查询时间。
  2. ef_construction: 控制索引构建时的搜索深度。较高的值通常会提高召回率和构建时间。

创建HNSW索引

以下是创建HNSW索引的示例:

CREATE INDEX ON items USING hnsw (vector) WITH (m = 16, ef_construction = 200);

调整参数以优化召回率

为了优化召回率,可以适当增加Mef_construction的值。例如:

CREATE INDEX ON items USING hnsw (vector) WITH (m = 32, ef_construction = 500);

查询示例

创建HNSW索引后,可以使用向量相似度搜索进行查询。例如,要查找与查询向量[0.1, 0.2, 0.3]相似的前3个结果,可以使用以下查询:

SELECT id, vector, vector <=> '[0.1, 0.2, 0.3]' AS distance
FROM items
ORDER BY vector <=> '[0.1, 0.2, 0.3]'
LIMIT 3;

使用Python进行批量查询

同样可以使用Python进行批量查询,并行处理以提高效率:

from concurrent.futures import ThreadPoolExecutor
import psycopg2

def query_similar_vectors_batch(query_vector_batch, threshold, top_k):
    conn = psycopg2.connect(
        dbname="your_database",
        user="your_user",
        password="your_password",
        host="your_host",
        port="your_port"
    )
    cur = conn.cursor()
    
    results = []
    for query_vector in query_vector_batch:
        query = """
        SELECT id, vector, vector <=> %s AS distance
        FROM items
        WHERE vector <=> %s < %s
        ORDER BY vector <=> %s
        LIMIT %s;
        """
        cur.execute(query, (query_vector, query_vector, threshold, query_vector, top_k))
        results.extend(cur.fetchall())

    cur.close()
    conn.close()
    
    return results

def batch_query_similar_vectors(query_vectors, threshold, top_k, batch_size):
    with ThreadPoolExecutor(max_workers=10) as executor:
        futures = [
            executor.submit(query_similar_vectors_batch, query_vectors[i:i + batch_size], threshold, top_k)
            for i in range(0, len(query_vectors), batch_size)
        ]
        results = []
        for future in futures:
            results.extend(future.result())
    return results

query_vectors = [...]  # 5000个长文本向量列表
threshold = 0.8
top_k = 3
batch_size = 500  # 每批次处理500个向量

results = batch_query_similar_vectors(query_vectors, threshold, top_k, batch_size)
for result in results:
    print(result)

通过使用HNSW索引并调整其参数,可以在保证查询效率的同时提高召回率,从而更好地满足你的需求。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值