# 定义项目原则 /speckit.constitution Create principles focused on: - Code quality: clean code, no duplication - Testing: unit tests required for all logic - Performance: response time < 200ms
defbrute_force_search(query, database, k=10): """暴力搜索""" # 计算所有相似度 similarities = [cosine_similarity(query, vec) for vec in database] # 排序取 Top-K indices = np.argsort(similarities)[-k:] return indices, [similarities[i] for i in indices]
复杂度分析:
时间:O(N × d),N 为向量数,d 为维度
空间:O(1),无需额外索引
问题:N 达到百万级时,单次查询耗时秒级,无法满足实时需求。
2. 维度灾难(Curse of Dimensionality)
高维空间的几何特性与低维截然不同:
维度
特性
2D/3D
距离有意义,近邻真的”近”
高维(>100)
所有向量距离趋于均匀,近邻与远邻差距缩小
定量分析:在 d 维超立方体中,随机两点距离的方差:
随着 d 增加,距离分布趋于集中,”最近”和”最远”的区分度下降。
结论:高维空间中,精确找到最近邻代价极高,但”足够近”的近似最近邻(ANN)足够好——这是 ANN 算法的理论基础。
1. 确定插入层数 l = floor(-ln(uniform(0,1)) × mL) 2. 从顶层 entry point 开始,贪心搜索到 l 层的入口 3. 从 l 层向下到 0 层,每层: a. 在当前层搜索 efConstruction 个最近邻候选 b. 从候选中选择 M 个最近邻连接 c. 处理连接边:保持每节点最大 M 条边
关键参数:
M:每节点最大连接数(默认 16)
efConstruction:构建时搜索宽度(默认 200)
mL:层数乘数,通常取 $1/\ln M$
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
# HNSW 构建伪代码 definsert(q, hnsw, M=16, ef_construction=200, mL=1/np.log(16)): # 1. 确定插入层数 level = int(-np.log(np.random.random()) * mL) # 2. 从顶层搜索到 level 层的入口 entry = hnsw.entry_point for l in range(hnsw.max_level, level + 1): entry = greedy_search(q, entry, ef=1, layer=l) # 3. 从 level 层向下插入 for l in range(level, -1, -1): candidates = search_layer(q, entry, ef_construction, l) neighbors = select_neighbors(q, candidates, M) connect(q, neighbors, l)
defpq_distance(query, pq_code, codebooks, m=8): """PQ 距离计算""" # 1. 预计算距离表 # distance_table[i][k] = distance(query的第i段, 第i个码本的第k个中心) distance_table = precompute_distance_table(query, codebooks, m) # 2. 查表累加 d = 0 for i in range(m): d += distance_table[i][pq_code[i]] return d
sqlCopy codeLOAD DATA INFILE 'data.csv' INTO TABLE employees FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' ( employee_id, first_name, last_name, email, hire_date DATE 'YYYY-MM-DD' ) WHEN (hire_date >= '2022-02-01')
将 select * from order_info order by id limit 5 offset 10 改写成 select * from order_info order by id limit 5 offset 3。偏移量10变成3,是基于10/3计算得出的。将语句在三个库分别执行,得到数据:
第二步:找最小值
第一个库:最小数据为8
第二个库:最小数据为11
第三个库:最小数据为12
因此,从三个库中拿到的最小数据为8。
第三步:第二次语句改写
这次需要把 select * from order_info order by id limit 5 offset 3 改写成一个between语句,起点是最小的OrderID,终点是原来每个分库各自返回数据的最大值:
第一个分库改写为: select * from order_info order by id where id between id_min and 22
第二个分库改写为: select * from order_info order by id where id between id_min and 23
第三个分库改写为: select * from order_info order by id where id between id_min and 24