upsert!以非分区键为更新键时跨分区执行插入而非更新
问题解答
1. upsert!的分区行为
是的,upsert!在分区表上仅会在新行所属的目标分区内查找匹配的key行。这是因为DolphinDB的分区表设计为分区独立操作,原生upsert!会根据新行的分区键(这里是update)定位到对应分区,仅在该分区内执行更新/插入逻辑,不会遍历其他分区。这就是为什么当新行和旧行id相同但update分属不同分区时,会插入新行而非更新旧行。
2. 跨分区upsert的实现方案
原生upsert!不支持通过非分区键实现跨分区upsert,但可以通过自定义逻辑模拟该行为,核心思路是先删除全表中匹配key的旧行,再插入新行:
自定义跨分区upsert函数
def crossPartitionUpsert(targetTable, newData, keyCols): # 提取新数据中的唯一key值 targetKeys = newData[keyCols].distinct() # 查询全表中所有匹配key的旧行 oldRecords = select * from targetTable where keyCols in targetKeys # 如果存在旧行则删除 if oldRecords.size() > 0: targetTable.delete!(oldRecords) # 插入新数据 targetTable.append!(newData)
使用示例
替换原有的upsert!调用:
crossPartitionUpsert(t, table(1 as id, 2024.01.02 as update, 200 as val), `id) select * from t // 输出结果: // id=1, update=2024-01-02, val=200
3. 注意事项与优化建议
- 性能影响:自定义方法需要跨分区查询和删除,数据量较大时性能会比原生
upsert!差,因为涉及多分区扫描。 - 分区策略调整:如果业务中频繁需要跨分区upsert,建议重新评估分区策略。例如:
- 将
id作为哈希分区键(保证同id的行在同一分区),再结合update做复合分区; - 如果
id是全局唯一主键,考虑将id作为唯一键而非依赖分区表的upsert逻辑。
- 将
内容的提问来源于stack exchange,提问作者Lorne_S
相关产品推荐
相关产品推荐

