MaxKB数据库优化:索引与查询优化

MaxKB数据库优化:索引与查询优化

【免费下载链接】MaxKB 💬 基于 LLM 大语言模型的知识库问答系统。开箱即用,支持快速嵌入到第三方业务系统,1Panel 官方出品。 【免费下载链接】MaxKB 项目地址: https://gitcode.com/GitHub_Trending/ma/MaxKB

引言

在构建基于LLM大语言模型的知识库问答系统时,数据库性能直接决定了系统的响应速度和用户体验。MaxKB作为企业级智能体平台,在处理海量文档、向量数据和搜索查询时面临着严峻的数据库性能挑战。本文将深入探讨MaxKB的数据库架构,并提供专业的索引优化和查询优化策略。

MaxKB数据库架构概览

MaxKB采用PostgreSQL + pgvector的技术栈,主要包含以下核心表结构:

mermaid

索引优化策略

1. 核心表索引设计

根据MaxKB的业务场景,以下是推荐的索引配置:

-- 知识库表索引
CREATE INDEX idx_knowledge_workspace ON knowledge(workspace_id);
CREATE INDEX idx_knowledge_type ON knowledge(type);
CREATE INDEX idx_knowledge_scope ON knowledge(scope);
CREATE INDEX idx_knowledge_folder ON knowledge(folder_id);

-- 文档表索引
CREATE INDEX idx_document_knowledge ON document(knowledge_id);
CREATE INDEX idx_document_status ON document(status);
CREATE INDEX idx_document_is_active ON document(is_active);
CREATE INDEX idx_document_type ON document(type);

-- 段落表索引
CREATE INDEX idx_paragraph_document ON paragraph(document_id);
CREATE INDEX idx_paragraph_knowledge ON paragraph(knowledge_id);
CREATE INDEX idx_paragraph_title ON paragraph(title);
CREATE INDEX idx_paragraph_status ON paragraph(status);
CREATE INDEX idx_paragraph_is_active ON paragraph(is_active);
CREATE INDEX idx_paragraph_position ON paragraph(position);

-- 向量表索引
CREATE INDEX idx_embedding_source_id ON embedding(source_id);
CREATE INDEX idx_embedding_source_type ON embedding(source_type);
CREATE INDEX idx_embedding_is_active ON embedding(is_active);
CREATE INDEX idx_embedding_knowledge ON embedding(knowledge_id);
CREATE INDEX idx_embedding_document ON embedding(document_id);
CREATE INDEX idx_embedding_paragraph ON embedding(paragraph_id);

2. 复合索引优化

对于频繁的联合查询,建议创建复合索引:

-- 知识库工作空间和类型复合索引
CREATE INDEX idx_knowledge_workspace_type ON knowledge(workspace_id, type);

-- 文档状态和活跃状态复合索引
CREATE INDEX idx_document_status_active ON document(status, is_active);

-- 段落文档和位置复合索引
CREATE INDEX idx_paragraph_doc_position ON paragraph(document_id, position);

3. 向量索引优化

pgvector支持多种索引类型,针对不同场景选择合适的索引:

索引类型适用场景优点缺点
IVFFlat中等规模数据集查询速度快精度相对较低
HNSW大规模数据集高精度、快速查询内存占用高
PQ超大规模数据集内存效率高精度损失

推荐配置:

-- 创建HNSW索引(推荐用于生产环境)
CREATE INDEX idx_embedding_vector_hnsw ON embedding 
USING hnsw (embedding vector_cosine_ops) 
WITH (m = 16, ef_construction = 200);

-- 或者使用IVFFlat索引(适用于中等规模)
CREATE INDEX idx_embedding_vector_ivf ON embedding 
USING ivfflat (embedding vector_cosine_ops) 
WITH (lists = 100);

查询优化实战

1. 向量搜索查询优化

MaxKB的核心搜索功能基于以下SQL模板:

SELECT
    paragraph_id,
    comprehensive_score,
    comprehensive_score as similarity
FROM
    (
    SELECT DISTINCT ON
        ("paragraph_id") ( 1 - distince ),* ,(1 - distince) AS comprehensive_score
    FROM
        ( SELECT *, ( embedding.embedding::vector(%s) <=>  %s ) AS distince 
          FROM embedding ${embedding_query} 
          ORDER BY distince) TEMP
    ORDER BY
        paragraph_id,
        distince
    ) DISTINCT_TEMP
WHERE comprehensive_score > %s
ORDER BY comprehensive_score DESC
LIMIT %s

优化建议:

索引层面:

  • 确保embedding字段有合适的向量索引
  • 为paragraph_id创建索引以加速DISTINCT操作

查询层面:

-- 使用CTE优化复杂查询
WITH ranked_embeddings AS (
    SELECT 
        paragraph_id,
        (1 - (embedding.embedding::vector(%s) <=> %s)) as similarity,
        ROW_NUMBER() OVER (PARTITION BY paragraph_id ORDER BY (embedding.embedding::vector(%s) <=> %s)) as rn
    FROM embedding 
    WHERE ${embedding_conditions}
)
SELECT 
    paragraph_id,
    similarity as comprehensive_score
FROM ranked_embeddings
WHERE rn = 1 AND similarity > %s
ORDER BY similarity DESC
LIMIT %s;

2. 混合搜索优化

混合搜索结合了向量搜索和全文搜索:

SELECT
    paragraph_id,
    comprehensive_score,
    comprehensive_score AS similarity
FROM
    (
    SELECT DISTINCT ON
        ( "paragraph_id" ) ( 1 - distince + ts_similarity ) as similarity, *,
        (1 - distince + ts_similarity) AS comprehensive_score
    FROM
        (
        SELECT
            *,
            (embedding.embedding::vector(%s) <=>  %s) as distince,
            (ts_rank_cd( embedding.search_vector, websearch_to_tsquery('simple', %s ), 32 )) AS ts_similarity
        FROM
            embedding ${embedding_query}
            ORDER BY distince
        ) TEMP
    ORDER BY
        paragraph_id,
        similarity DESC
    ) DISTINCT_TEMP
WHERE
    comprehensive_score > %s
ORDER BY
    comprehensive_score DESC
    LIMIT %s

优化策略:

索引优化:

-- 为search_vector创建GIN索引
CREATE INDEX idx_embedding_search_vector ON embedding USING GIN (search_vector);

-- 创建复合索引加速混合查询
CREATE INDEX idx_embedding_mixed_search ON embedding 
USING GIN (search_vector, (embedding::vector));

查询重写:

-- 使用窗口函数优化混合搜索
WITH scored_embeddings AS (
    SELECT 
        paragraph_id,
        (1 - (embedding::vector(%s) <=> %s)) as vector_score,
        ts_rank_cd(search_vector, websearch_to_tsquery('simple', %s), 32) as text_score,
        (1 - (embedding::vector(%s) <=> %s) + 
         ts_rank_cd(search_vector, websearch_to_tsquery('simple', %s), 32)) as combined_score,
        ROW_NUMBER() OVER (PARTITION BY paragraph_id ORDER BY (1 - (embedding::vector(%s) <=> %s)) DESC) as rn
    FROM embedding
    WHERE ${embedding_conditions}
)
SELECT 
    paragraph_id,
    combined_score as comprehensive_score
FROM scored_embeddings
WHERE rn = 1 AND combined_score > %s
ORDER BY combined_score DESC
LIMIT %s;

3. 分页查询优化

对于大数据集的分页查询,避免使用OFFSET:

-- 传统分页(不推荐)
SELECT * FROM paragraph 
WHERE knowledge_id = %s 
ORDER BY position 
OFFSET 1000 LIMIT 50;

-- 优化后的分页(推荐)
SELECT * FROM paragraph 
WHERE knowledge_id = %s AND position > (SELECT position FROM paragraph WHERE id = %s)
ORDER BY position 
LIMIT 50;

性能监控与调优

1. 关键性能指标监控

-- 查询缓存命中率
SELECT 
    sum(heap_blks_read) as heap_read,
    sum(heap_blks_hit)  as heap_hit,
    sum(heap_blks_hit) / (sum(heap_blks_hit) + sum(heap_blks_read)) as ratio
FROM pg_statio_user_tables;

-- 索引使用情况
SELECT 
    schemaname,
    relname,
    indexrelname,
    idx_scan,
    idx_tup_read,
    idx_tup_fetch
FROM pg_stat_user_indexes 
ORDER BY idx_scan DESC;

-- 慢查询分析
SELECT 
    query, 
    calls, 
    total_time, 
    rows, 
    total_time/calls as avg_time,
    rows/calls as avg_rows
FROM pg_stat_statements 
ORDER BY total_time DESC 
LIMIT 10;

2. 连接池配置

推荐使用PgBouncer进行连接池管理:

[databases]
maxkb = host=localhost dbname=maxkb user=maxkb_user

[pgbouncer]
pool_mode = transaction
max_client_conn = 1000
default_pool_size = 20
reserve_pool_size = 5

3. 定期维护任务

# 每日 vacuum 分析
vacuumdb -z -a

# 每周 reindex
reindexdb -a

# 每月统计信息更新
analyzedb -a

实战案例:千万级数据优化

假设知识库包含1000万条段落数据,优化方案如下:

1. 分区策略

-- 按知识库ID进行分区
CREATE TABLE paragraph_ptn (
    LIKE paragraph INCLUDING ALL
) PARTITION BY HASH (knowledge_id);

-- 创建16个分区
CREATE TABLE paragraph_p0 PARTITION OF paragraph_ptn FOR VALUES WITH (MODULUS 16, REMAINDER 0);
CREATE TABLE paragraph_p1 PARTITION OF paragraph_ptn FOR VALUES WITH (MODULUS 16, REMAINDER 1);
-- ... 创建剩余14个分区

2. 批量处理优化

# 批量插入优化示例
from django.db import transaction

@transaction.atomic
def batch_create_paragraphs(paragraphs_data, batch_size=1000):
    paragraphs = []
    for i, data in enumerate(paragraphs_data):
        paragraph = Paragraph(**data)
        paragraphs.append(paragraph)
        
        if i % batch_size == 0 and i > 0:
            Paragraph.objects.bulk_create(paragraphs)
            paragraphs = []
    
    if paragraphs:
        Paragraph.objects.bulk_create(paragraphs)

3. 异步处理架构

mermaid

总结

MaxKB数据库优化是一个系统工程,需要从索引设计、查询优化、架构设计等多个层面综合考虑。通过合理的索引策略、查询重写、分区设计和异步处理,可以显著提升系统性能,支撑千万级知识库数据的快速检索。

关键优化要点:

  • 为高频查询字段创建合适的索引
  • 使用复合索引减少回表操作
  • 选择合适的向量索引类型(HNSW推荐)
  • 优化分页查询,避免OFFSET性能问题
  • 实施分区策略处理超大规模数据
  • 建立完善的监控和维护体系

通过以上优化策略,MaxKB可以在保持高精度的同时,实现毫秒级的搜索响应,为用户提供流畅的知识问答体验。

【免费下载链接】MaxKB 💬 基于 LLM 大语言模型的知识库问答系统。开箱即用,支持快速嵌入到第三方业务系统,1Panel 官方出品。 【免费下载链接】MaxKB 项目地址: https://gitcode.com/GitHub_Trending/ma/MaxKB

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值