关系数据与向量数据联合查询
2026/9/12 21:13:34 网站建设 项目流程

文章目录

    • 每日一句正能量
    • 1. 背景与问题
    • 2. 环境与数据
      • 2.1 客户关系表
      • 2.2 文档画像和向量表
      • 2.3 客户行为时序表
    • 3. 复现过程
      • 3.1 只有关系筛选的局限
      • 3.2 只有向量检索的风险
      • 3.3 复现过滤后置问题
    • 4. 方案实施
      • 4.1 先定义强约束
      • 4.2 关系与向量联合查询
      • 4.3 组合 JSONB 标签
      • 4.4 使用时序行为重排
      • 4.5 性能观察
      • 4.6 部署与验证
    • 5. 结果对比
      • 5.1 性能与效果可视化分析
    • 6. 风险与复盘
      • 6.1 常见风险
      • 6.2 RTO 与 RPO
      • 6.3 复盘结论

每日一句正能量

“最美的蜕变常常包裹着最难熬的磨砺。”
最高价值的获得,往往与最艰难的付出成正比。
不抗拒命运,但始终选择看见光亮;不否认黑暗,但坚信根在生长。在日常中活出——一种清醒的、优美的、属于你自己的“活着”。

1. 背景与问题

客户画像系统通常已经积累了大量结构化信息:客户等级、注册时间、所属区域、会员状态、消费金额、标签、最近活跃时间、投诉记录等。这些数据适合用关系数据库进行精确筛选。

例如,运营人员可以找到“近 90 天未消费、累计消费超过 5000 元、位于华东区域的客户”:

SELECTcustomer_id,customer_name,total_spendFROMcustomerWHEREregion_codeIN('CN-SH','CN-JS','CN-ZJ')ANDtotal_spend>=5000ANDlast_purchase_at<now()-interval'90 days';

但实际运营问题通常不止于精确筛选。运营人员还会提出语义型需求:

找出与近期频繁询问价格保护、续费优惠、竞品对比的高价值沉默客户相似的人群。

这类问题无法只靠LIKE、枚举标签或固定规则解决。客户咨询摘要、客服会话、工单说明和运营备注中包含大量自然语言信息,同样的意图可能有不同表达:

续费太贵,准备换其他平台。 现在有没有保价活动? 别家的方案价格低很多。 会员到期后暂时不考虑继续购买。

如果只使用关系条件,无法识别这些语义相近但词面不同的客户;如果只使用向量检索,又可能返回不符合客户等级、区域、授权范围和营销规则的人群。

因此,客户画像检索应采用多模联合方式:

关系数据:客户等级、区域、消费、会员状态、合规状态; 文档数据:标签、会话摘要、工单内容和动态属性; 时序数据:访问、咨询、购买、退款和投诉变化; 向量数据:客户意图、相似问题和语义特征。

核心原则是:

关系条件定义“哪些客户可以进入候选集”; 向量检索定义“候选客户与目标意图是否相似”; 时序行为定义“客户当前是否值得触达”; 文档属性补充“为什么被选中”的解释。

2. 环境与数据

实验环境:

组件用途
PostgreSQL 15客户主数据、权限、运营任务
pgvector会话摘要和客户意图向量
JSONB兴趣标签、渠道、偏好和扩展属性
TimescaleDB浏览、咨询、订单、退款等行为事件
Embedding 服务将客户会话摘要转换为向量
查询 API条件校验、联合检索、审计和结果解释

2.1 客户关系表

CREATETABLEcustomer(customer_id UUIDPRIMARYKEY,tenant_idTEXTNOTNULL,customer_nameTEXTNOTNULL,customer_levelTEXTNOTNULL,region_codeTEXTNOTNULL,member_statusTEXTNOTNULL,total_spendNUMERIC(14,2)NOTNULLDEFAULT0,last_purchase_at TIMESTAMPTZ,marketing_consentBOOLEANNOTNULLDEFAULTFALSE,statusTEXTNOTNULLDEFAULT'active',created_at TIMESTAMPTZNOTNULLDEFAULTnow());CREATEINDEXidx_customer_segmentONcustomer(tenant_id,status,marketing_consent,customer_level,region_code,total_spend);

marketing_consent是强约束字段。无论向量相似度多高,未授权营销触达的客户都不能进入运营名单。

2.2 文档画像和向量表

CREATEEXTENSIONIFNOTEXISTSvector;CREATETABLEcustomer_profile_document(customer_id UUIDPRIMARYKEYREFERENCEScustomer(customer_id),tenant_idTEXTNOTNULL,profile_summaryTEXTNOTNULL,tags JSONBNOTNULLDEFAULT'{}'::jsonb,updated_at TIMESTAMPTZNOTNULLDEFAULTnow());CREATETABLEcustomer_intent_embedding(embedding_id UUIDPRIMARYKEY,customer_id UUIDNOTNULLREFERENCEScustomer(customer_id),tenant_idTEXTNOTNULL,source_typeTEXTNOTNULL,source_time TIMESTAMPTZNOTNULL,summaryTEXTNOTNULL,embedding_modelTEXTNOTNULL,embedding VECTOR(768)NOTNULL,metadata JSONBNOTNULLDEFAULT'{}'::jsonb,statusTEXTNOTNULLDEFAULT'active');CREATEINDEXidx_customer_embedding_hnswONcustomer_intent_embeddingUSINGhnsw(embedding vector_cosine_ops);CREATEINDEXidx_customer_embedding_filterONcustomer_intent_embedding(tenant_id,status,customer_id);CREATEINDEXidx_customer_profile_tagsONcustomer_profile_documentUSINGGIN(tags);

source_type可以用于区分向量来源:

service_chat ticket_summary sales_note survey_feedback complaint

2.3 客户行为时序表

CREATEEXTENSIONIFNOTEXISTStimescaledb;CREATETABLEcustomer_event(ts TIMESTAMPTZNOTNULL,tenant_idTEXTNOTNULL,customer_id UUIDNOTNULL,event_typeTEXTNOTNULL,event_valueNUMERIC(14,2),attributes JSONBNOTNULLDEFAULT'{}'::jsonb);SELECTcreate_hypertable('customer_event',by_range('ts'),if_not_exists=>TRUE);CREATEINDEXidx_customer_event_lookupONcustomer_event(tenant_id,customer_id,event_type,tsDESC);

事件类型示例:

page_view consultation purchase refund complaint campaign_click coupon_claim

3. 复现过程

3.1 只有关系筛选的局限

下面 SQL 可以找出高价值沉默客户:

SELECTcustomer_id,customer_name,total_spend,last_purchase_atFROMcustomerWHEREtenant_id='tenant_a'ANDstatus='active'ANDmarketing_consent=TRUEANDcustomer_levelIN('gold','platinum')ANDtotal_spend>=5000ANDlast_purchase_at<now()-interval'90 days';

但这条查询无法判断客户沉默的原因。客户可能是满意但暂时没有需求,也可能是对价格、服务、竞品或产品功能存在不满。对所有人使用同一种召回活动,转化率通常不高。

3.2 只有向量检索的风险

错误方式是全量寻找“价格敏感”客户:

SELECTcustomer_id,summary,1-(embedding<=>$1::vector)ASsimilarityFROMcustomer_intent_embeddingWHEREtenant_id='tenant_a'ANDstatus='active'ORDERBYembedding<=>$1::vectorLIMIT100;

这会包含:

  • 已注销客户。
  • 未授权营销的客户。
  • 消费能力不匹配的客户。
  • 不在当前活动区域的客户。
  • 已投诉且不适合触达的客户。

向量相似度只能说明文本意图接近,不能替代业务资格判断。

3.3 复现过滤后置问题

WITHvector_topAS(SELECTcustomer_id,summary,1-(embedding<=>$1::vector)ASsimilarityFROMcustomer_intent_embeddingWHEREtenant_id='tenant_a'ORDERBYembedding<=>$1::vectorLIMIT100)SELECTv.customer_id,v.summary,v.similarityFROMvector_top vJOINcustomer cONc.customer_id=v.customer_idWHEREc.marketing_consent=TRUEANDc.customer_levelIN('gold','platinum')ANDc.status='active'ORDERBYv.similarityDESCLIMIT20;

如果全局 Top-100 中大部分客户不符合营销资格,过滤后可能只剩少量结果。更严重的是,无资格客户已进入应用候选集、日志或后续模型上下文。

4. 方案实施

4.1 先定义强约束

客户画像检索必须区分强约束和弱排序。

类型字段示例处理方式
强约束租户、客户状态、营销授权、区域、黑名单必须在 SQL 中过滤
业务筛选客户等级、累计消费、会员状态、最近消费时间通常在 SQL 中过滤
弱排序意图相似度、近期浏览、活动点击、购买趋势用于候选重排
解释信息标签、会话摘要、客服备注用于结果说明

4.2 关系与向量联合查询

目标是找到“高价值、已授权、超过 90 天未消费、且与价格敏感咨询语义相似”的客户。

WITHeligible_customerAS(SELECTc.customer_id,c.customer_name,c.customer_level,c.region_code,c.total_spend,c.last_purchase_atFROMcustomer cWHEREc.tenant_id=$2ANDc.status='active'ANDc.marketing_consent=TRUEANDc.customer_levelIN('gold','platinum')ANDc.total_spend>=5000ANDc.last_purchase_at<now()-interval'90 days'),vector_candidatesAS(SELECTe.customer_id,e.summary,e.source_time,1-(e.embedding<=>$1::vector)ASsemantic_scoreFROMcustomer_intent_embedding eJOINeligible_customer cONc.customer_id=e.customer_idWHEREe.tenant_id=$2ANDe.status='active'ANDe.source_typeIN('service_chat','ticket_summary')ORDERBYe.embedding<=>$1::vectorLIMIT200)SELECTc.customer_id,c.customer_name,c.customer_level,c.region_code,c.total_spend,v.summary,v.source_time,v.semantic_scoreFROMvector_candidates vJOINeligible_customer cONc.customer_id=v.customer_idORDERBYv.semantic_scoreDESCLIMIT20;

该查询先使用关系模型限制业务边界,再使用向量模型排序。最终结果既符合营销规则,也保留语义相关性。

4.3 组合 JSONB 标签

客户画像往往有动态标签,例如:

{"preferred_channel":"wechat","product_interest":["database","monitoring"],"price_sensitivity":"high","industry":"retail"}

查询“偏好微信触达、对数据库产品感兴趣”的客户:

SELECTc.customer_id,c.customer_name,p.tags,1-(e.embedding<=>$1::vector)ASsemantic_scoreFROMcustomer cJOINcustomer_profile_document pONp.customer_id=c.customer_idJOINcustomer_intent_embedding eONe.customer_id=c.customer_idWHEREc.tenant_id=$2ANDc.status='active'ANDc.marketing_consent=TRUEANDp.tags @>'{"preferred_channel":"wechat"}'ANDp.tags->'product_interest'?'database'ANDe.status='active'ORDERBYe.embedding<=>$1::vectorLIMIT20;

高频筛选项应保留在普通列中。JSONB 更适合承载变化快、维度多、难以预先穷举的画像属性。

4.4 使用时序行为重排

向量结果相似不代表客户当前值得触达。可以按近 30 天行为进行重排:

WITHbehaviorAS(SELECTcustomer_id,count(*)FILTER(WHEREevent_type='campaign_click')AScampaign_clicks_30d,count(*)FILTER(WHEREevent_type='consultation')ASconsultations_30d,max(ts)ASlast_active_atFROMcustomer_eventWHEREtenant_id=$2ANDts>=now()-interval'30 days'GROUPBYcustomer_id),semantic_candidatesAS(SELECTe.customer_id,max(1-(e.embedding<=>$1::vector))ASsemantic_scoreFROMcustomer_intent_embedding eJOINcustomer cONc.customer_id=e.customer_idWHEREe.tenant_id=$2ANDc.status='active'ANDc.marketing_consent=TRUEANDc.total_spend>=5000ANDe.status='active'GROUPBYe.customer_idORDERBYmax(1-(e.embedding<=>$1::vector))DESCLIMIT200)SELECTs.customer_id,s.semantic_score,coalesce(b.campaign_clicks_30d,0)AScampaign_clicks_30d,coalesce(b.consultations_30d,0)ASconsultations_30d,s.semantic_score*0.75+ln(1+coalesce(b.campaign_clicks_30d,0))*0.15+ln(1+coalesce(b.consultations_30d,0))*0.10ASfinal_scoreFROMsemantic_candidates sLEFTJOINbehavior bONb.customer_id=s.customer_idORDERBYfinal_scoreDESCLIMIT20;

这里的时序信号只用于排序,不能覆盖营销授权、黑名单、客户状态等强约束。

4.5 性能观察

使用以下 SQL 查看联合查询计划:

EXPLAIN(ANALYZE,BUFFERS)SELECTe.customer_id,1-(e.embedding<=>$1::vector)ASsemantic_scoreFROMcustomer_intent_embedding eJOINcustomer cONc.customer_id=e.customer_idWHEREe.tenant_id='tenant_a'ANDe.status='active'ANDc.status='active'ANDc.marketing_consent=TRUEANDc.total_spend>=5000ORDERBYe.embedding<=>$1::vectorLIMIT20;

重点检查:

是否先过滤租户和授权; Rows Removed by Filter 是否过高; 向量索引是否真正参与查询; Buffers 是否出现异常增长; 不同客户分群下 P95 延迟是否稳定; 过滤后 Top-K 是否仍能返回足够候选。

4.6 部署与验证

建议上线前执行以下验证:

[ ] 未授权营销客户不会进入任何候选集。 [ ] 已注销、黑名单和冻结客户不会被向量召回。 [ ] 同一客户多条会话不会重复占满 Top-K。 [ ] 画像标签更新后,查询结果能够及时反映。 [ ] 向量生成失败时,旧向量是否仍可控使用。 [ ] 时序行为服务异常时,系统能回退到语义排序。 [ ] 查询日志不记录完整敏感会话内容。

5. 结果对比

以下是用于说明评估方法的示例结果,正式发布应替换为真实压测与业务统计数据。

方案客户资格合规率Top-20 语义相关率P95 延迟人群重复率
仅关系筛选100%58%35 ms
仅向量检索74%84%72 ms
向量后置过滤100%69%88 ms
关系过滤下推 + 向量排序100%82%96 ms
联合查询 + 时序重排100%85%118 ms

从结果可以看出:

  • 只用关系筛选,合规但难理解客户当前意图。
  • 只用向量检索,语义较强但容易违反业务规则。
  • 后置过滤会造成候选浪费和 Top-K 不足。
  • 关系过滤下推后,语义结果和业务资格可以同时满足。
  • 时序行为重排能提升“当前可触达性”,但应严格控制权重。

建议持续监控:

授权过滤拦截数; Top-K 不足率; 客户重复出现率; 向量召回耗时; 时序行为聚合耗时; 活动触达后的点击、咨询和转化; 投诉率与退订率。

5.1 性能与效果可视化分析

为了更直观地对比各方案的差异,下面基于表格数据绘制两张 ASCII 图表。

图 1:客户资格合规率与 Top-20 语义相关率对比

合规率 / 相关率 (%) 100 | ●───────────────●───────────────●───────────────● | │ │ │ │ 90 | │ │ │ │ | │ │ │ │ 80 | │ │ ●───● │ ●───● │ | │ │ │ │ │ │ │ │ 70 | │ │ ●───┤ │ │ │ │ │ | │ │ │ │ │ │ │ │ │ 60 | │ ●───● │ │ │ │ │ │ │ │ | │ │ │ │ │ │ │ │ │ │ │ 50 | └───┴───┴───────┴───┴───┴───┴───┴───────┴───┴───┴──▶ | 仅关系筛选 仅向量检索 向量后置过滤 关系过滤下推 联合查询 | + 向量排序 + 时序重排 | | ● = 客户资格合规率 ■ = Top-20 语义相关率

图 2:P95 延迟递增趋势

P95 延迟 (ms) 120 | ●───────────────● | │ │ 100 | ●───────────────●───┤ │ | │ │ │ │ 80 | ●───────────┤ │ │ │ | │ │ │ │ │ 60 | ●────┤ │ │ │ │ | │ │ │ │ │ │ 40 | │ │ │ │ │ │ | │ │ │ │ │ │ 20 | └────┴───────────┴───────────────┴───┴───────────────┴──▶ | 仅关系筛选 仅向量检索 向量后置过滤 关系过滤下推 联合查询 | + 向量排序 + 时序重排

从两张图可以清晰看出:「关系过滤下推 + 向量排序」是性价比最优的方案。它在保持 100% 客户资格合规率的同时,将 Top-20 语义相关率从「仅关系筛选」的 58% 大幅提升至 82%,而 P95 延迟仅从 35ms 增加到 96ms,相比「仅向量检索」的 72ms 也只多了 24ms,却换来了合规率从 74% 到 100% 的质变,彻底消除了业务违规风险。相比之下,「联合查询 + 时序重排」虽然把语义相关率进一步推高到 85%,但代价是延迟从 96ms 增至 118ms,增加了 22ms。这 3% 的相关率提升是否值得,取决于业务场景:对于客单价高、转化周期长的精细化运营场景,多花 22ms 换取更精准的触达名单、减少无效打扰,通常是划算的;但对于对延迟极度敏感、且已有足够候选量的场景,这 3% 的边际收益可能并不明显,此时「关系过滤下推 + 向量排序」已能覆盖绝大多数需求。

6. 风险与复盘

6.1 常见风险

风险表现应对措施
只做向量检索返回不符合资格的客户强约束下推到 SQL
过滤条件后置Top-K 过滤后不足在候选前过滤
画像数据过期触达策略失效设置更新时间和有效期
标签滥用 JSONB高频查询变慢高频字段列化并建立索引
多会话重复召回单客户占据候选列表按 customer_id 聚合或去重
时序数据滞后热度排序偏差标记数据延迟并设置回退
营销授权遗漏合规风险授权作为强制条件
会话摘要泄露敏感信息暴露脱敏、最小化展示与审计
向量模型混用分数无法比较记录模型版本并分批重建

6.2 RTO 与 RPO

项目建议目标
客户主数据 RPO0
营销授权变更生效1 分钟内
客户画像更新到可检索10 分钟内
向量索引故障 RTO30 分钟内降级或恢复
行为重排故障 RTO5 分钟内回退至语义排序
越权或违规触达容忍度0

6.3 复盘结论

关系数据与向量数据联合查询,不是把两张表简单JOIN起来,而是为不同数据能力划定职责:

关系数据负责资格、权限、状态和业务边界; 文档数据负责标签、偏好、来源和解释信息; 时序数据负责活跃度、趋势和触达时机; 向量数据负责自然语言意图和相似客户发现。

推荐的生产查询路径是:

校验租户、权限和营销授权 -> 关系筛选客户资格 -> 文档标签过滤画像范围 -> 向量检索相似意图 -> 客户维度去重 -> 时序行为重排 -> 输出可解释的触达名单 -> 记录审计与效果反馈

最终验收不能只关注“是否找到相似客户”,还必须确认:

  1. 客户是否满足业务和合规条件。
  2. 相似意图是否有客服摘要或标签作为解释。
  3. 近期时序行为是否支持当前触达决策。
  4. 查询延迟、候选数量和重复率是否可控。
  5. 用户反馈、退订率和投诉率是否被持续监控。

转载自:https://blog.csdn.net/u014727709/article/details/164884529
欢迎 👍点赞✍评论⭐收藏,欢迎指正

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询