Semantic View最佳实践:通过语义视图提升NL2SQL准确性

更新时间:
复制为 MD 格式

Semantic View(语义视图)将业务语义与底层数据模型解耦,为 NL2SQL 提供结构化的语义上下文,提升 LLM 生成 SQL 的准确性。

重要

Semantic View 功能目前处于内测阶段。如需使用,请提交工单或联系技术支持申请开通。

效果对比

传统 NL2SQL 场景中,LLM 仅依赖表结构信息生成 SQL,在多表关联和复杂计算场景下容易出错。以 TPC-H 数据集为例,直接向 Agent 提问"查询 1997 年亚洲地区各国的财务净额",常见错误包括:

  • JOIN 路径错误:关联了不相关的供应链表(partsupp),或使用了错误的数据库(外库而非目标库)。

  • 计算逻辑错误:误扣除成本(ps_supplycost),或使用了错误的聚合公式。

  • Token 消耗高:需要提供 5 张以上表结构信息,且需要多轮对话修正。

Semantic View 通过预定义维度、指标和表关系,让 LLM 直接获取业务语义,一次生成正确 SQL。对比如下:

指标

无 Semantic View

使用 Semantic View

结果正确性

JOIN 路径和计算逻辑容易出错

一次生成正确 SQL

对话轮次

3~5 轮(需多次修正)

1 轮

上下文需求

完整表结构(5+ 张表)

仅语义摘要

可复用性

每次查询需重复理解

一次定义,永久复用

前提条件

  • 已创建AnalyticDB for MySQL集群。具体操作,请参见创建集群。

  • 已申请开通 Semantic View 内测功能。请提交工单或联系技术支持。

  • 已准备支持 Skill 的 AI 编程工具(如 Claude Code)。

操作步骤

步骤一:准备数据和环境

  1. 创建数据库和 TPC-H 表。

    CREATE DATABASE IF NOT EXISTS tpch_demo;
    USE tpch_demo;
    -- 创建 orders 表
    CREATE TABLE IF NOT EXISTS orders (
      o_orderkey      BIGINT NOT NULL,
      o_custkey       BIGINT NOT NULL,
      o_orderstatus   VARCHAR(1),
      o_totalprice    DECIMAL(15,2),
      o_orderdate     DATE,
      o_orderpriority VARCHAR(15),
      o_clerk         VARCHAR(15),
      o_shippriority  INT,
      o_comment       VARCHAR(79),
      PRIMARY KEY (o_orderkey)
    );
    
    -- 创建 lineitem 表
    CREATE TABLE IF NOT EXISTS lineitem (
      l_orderkey      BIGINT NOT NULL,
      l_partkey       BIGINT NOT NULL,
      l_suppkey       BIGINT NOT NULL,
      l_linenumber    INT NOT NULL,
      l_quantity      DECIMAL(15,2),
      l_extendedprice DECIMAL(15,2),
      l_discount      DECIMAL(15,2),
      l_tax           DECIMAL(15,2),
      l_returnflag    VARCHAR(1),
      l_linestatus    VARCHAR(1),
      l_shipdate      DATE,
      l_commitdate    DATE,
      l_receiptdate   DATE,
      l_shipinstruct  VARCHAR(25),
      l_shipmode      VARCHAR(10),
      l_comment       VARCHAR(44),
      PRIMARY KEY (l_orderkey, l_linenumber)
    );
    
    -- 创建 customer 表
    CREATE TABLE IF NOT EXISTS customer (
      c_custkey    BIGINT NOT NULL,
      c_name       VARCHAR(25),
      c_address    VARCHAR(40),
      c_nationkey  BIGINT,
      c_phone      VARCHAR(15),
      c_acctbal    DECIMAL(15,2),
      c_mktsegment VARCHAR(10),
      c_comment    VARCHAR(117),
      PRIMARY KEY (c_custkey)
    );
  2. 导入 TPC-H 示例数据。可通过 dbgen 工具生成,或从 TPC-H 官方获取测试数据集。

    说明

    如已有 TPC-H 数据库,可跳过建表步骤,将后续 SQL 中的 tpch_demo 替换为实际数据库名。

  3. 在终端中设置数据库连接环境变量。

    export ADB_MYSQL_HOST="amv-xxxxx.ads.aliyuncs.com"
    export ADB_MYSQL_PORT="3306"
    export ADB_MYSQL_USER="your_username"
    export ADB_MYSQL_PASSWORD="your_password"

步骤二:安装 Skill

安装AnalyticDB for MySQL Smart Analyst Skill,用于通过自然语言管理 Semantic View 和执行 NL2SQL 查询。

  1. 执行以下命令安装 Skill:

    npx skills add aliyun/alibabacloud-adb-mysql-mcp-server

    也可以手动安装:

    git clone https://github.com/aliyun/alibabacloud-adb-mysql-mcp-server
    cd alibabacloud-adb-mysql-mcp-server/skill
    mkdir -p ~/.claude/skills/
    cp -r alibabacloud-adb-smart-analyst ~/.claude/skills/
  2. 验证数据库连通性。

    /alibabacloud-adb-smart-analyst 连通性测试

    连接成功时输出:

    连通性测试通过
    
      执行 SQL:SELECT 1 AS connectivity_test
    
      ┌───────────────────┐
      │ connectivity_test │
      ├───────────────────┤
      │ 1                 │
      └───────────────────┘
    
      数据库连接正常。

    如果连接失败,Skill 会提示设置环境变量,请参照步骤一第 3 步配置。

步骤三:创建和管理 Semantic View

Semantic View 通过 YAML 定义业务语义,嵌入在 CREATE OR REPLACE SEMANTIC VIEW 语句中。YAML 包含以下元素:

元素

说明

dimensions

用于 WHEREGROUP BY 的字段,如状态、地区

time_dimensions

时间类型的维度字段,用于按时间范围筛选和聚合

facts

原始数值字段(单价、折扣等),是计算指标的基础

metrics

基于 facts 的聚合表达式(总收入、平均金额等),对应业务 KPI

filters

预定义过滤条件,封装常见的业务筛选逻辑

relationships

表间 JOIN 路径,帮助 LLM 自动生成正确的多表关联查询

基于 TPC-H 的 lineitem、orders、customer 三张表,创建销售分析 Semantic View:

CREATE OR REPLACE SEMANTIC VIEW tpch_sales_analytics
LANGUAGE YAML
AS
$$
name: tpch_sales_analytics
description: TPC-H 销售分析语义视图,支持按客户、订单、时间等维度分析销售收入与发货表现。

tables:
  - name: lineitem
    base_table:
      schema: tpch_demo
      table: lineitem
    dimensions:
      - name: return_flag
        description: 退货标识。R 表示已退货,A 表示已接受,N 表示未处理。
        expr: l_returnflag
        data_type: varchar
      - name: line_status
        description: 订单行状态。O 表示未完成,F 表示已完成。
        expr: l_linestatus
        data_type: varchar
      - name: ship_mode
        description: 运输方式。包括 TRUCK、AIR、SHIP、RAIL、MAIL 等。
        expr: l_shipmode
        data_type: varchar
    time_dimensions:
      - name: ship_date
        description: 发货日期
        expr: l_shipdate
        data_type: date
    facts:
      - name: extended_price
        description: 商品原始金额
        expr: l_extendedprice
        data_type: decimal
      - name: discount
        description: 折扣比例,取值范围 0~1
        expr: l_discount
        data_type: decimal
      - name: quantity
        description: 商品数量
        expr: l_quantity
        data_type: decimal
    metrics:
      - name: revenue
        description: 折后总销售收入,计算公式为 SUM(原始金额 * (1 - 折扣))
        expr: SUM(l_extendedprice * (1 - l_discount))
      - name: total_quantity
        description: 商品总数量
        expr: SUM(l_quantity)
      - name: avg_price
        description: 平均商品单价
        expr: AVG(l_extendedprice)
      - name: late_shipping_rate
        description: 延迟发货率,即实际收货日期晚于承诺日期的比例
        expr: COUNT(CASE WHEN l_receiptdate > l_commitdate THEN 1 END) * 1.0 / COUNT(*)
    filters:
      - name: completed_only
        description: 仅包含已完成的订单行
        expr: l_linestatus = 'F'

  - name: orders
    base_table:
      schema: tpch_demo
      table: orders
    dimensions:
      - name: order_status
        description: 订单状态。O 表示未完成,F 表示已完成,P 表示部分完成。
        expr: o_orderstatus
        data_type: varchar
      - name: order_priority
        description: 订单优先级。包括 1-URGENT、2-HIGH、3-MEDIUM、4-NOT SPECIFIED、5-LOW。
        expr: o_orderpriority
        data_type: varchar
    time_dimensions:
      - name: order_date
        description: 下单日期
        expr: o_orderdate
        data_type: date
    facts:
      - name: total_price
        description: 订单总金额
        expr: o_totalprice
        data_type: decimal
    metrics:
      - name: order_count
        description: 订单总数
        expr: COUNT(*)
      - name: avg_order_value
        description: 平均订单金额
        expr: AVG(o_totalprice)

  - name: customer
    base_table:
      schema: tpch_demo
      table: customer
    dimensions:
      - name: market_segment
        description: 客户所属市场分类。包括 AUTOMOBILE、BUILDING、FURNITURE、HOUSEHOLD、MACHINERY。
        expr: c_mktsegment
        data_type: varchar
      - name: customer_name
        description: 客户名称
        expr: c_name
        data_type: varchar
    facts:
      - name: account_balance
        description: 客户账户余额
        expr: c_acctbal
        data_type: decimal

relationships:
  - name: lineitem_to_orders
    left_table: lineitem
    right_table: orders
    relationship_type: many_to_one
    on:
      - left_expr: l_orderkey
        right_expr: o_orderkey
  - name: orders_to_customer
    left_table: orders
    right_table: customer
    relationship_type: many_to_one
    on:
      - left_expr: o_custkey
        right_expr: c_custkey
$$;

确认 Semantic View 已创建:

SELECT view_schema, view_name, definition
FROM information_schema.semantic_views
WHERE view_name = 'tpch_sales_analytics';

也可以通过 Skill 使用自然语言管理 Semantic View:

-- 查询特定语义视图
/alibabacloud-adb-smart-analyst 查询 tpch_sales_analytics 语义视图的内容

-- 查看所有语义视图
/alibabacloud-adb-smart-analyst 查看有哪些语义视图

-- 删除语义视图
/alibabacloud-adb-smart-analyst 删除 tpch_demo.tpch_sales_analytics 语义视图

步骤四:NL2SQL 查询

Semantic View 创建完成后,通过 Skill 直接使用自然语言查询。Skill 自动执行语义搜索、表结构校验、SQL 生成与执行三个步骤。

示例:

/alibabacloud-adb-smart-analyst 各运输方式的总收入是多少?

返回结果:

查询结果

  执行 SQL:
  SELECT l_shipmode, SUM(l_extendedprice * (1 - l_discount)) AS revenue
  FROM tpch_demo.lineitem
  GROUP BY l_shipmode

  ┌───────────┬─────────────┐
  │ l_shipmode│   revenue   │
  ├───────────┼─────────────┤
  │ AIR       │ 258,217,431 │
  │ FOB       │ 261,609,629 │
  │ MAIL      │ 259,103,165 │
  │ RAIL      │ 260,370,880 │
  │ REG AIR   │ 260,012,778 │
  │ SHIP      │ 261,260,339 │
  │ TRUCK     │ 261,419,202 │
  └───────────┴─────────────┘

更多查询示例:

自然语言查询

生成的 SQL

1995 年下半年各客户分类的订单数和平均订单金额

SELECT c_mktsegment, COUNT(*) AS order_count, AVG(o_totalprice) AS avg_order_value FROM orders JOIN customer ON o_custkey = c_custkey WHERE o_orderdate >= '1995-07-01' AND o_orderdate < '1996-01-01' GROUP BY c_mktsegment

延迟发货率最高的运输方式

SELECT l_shipmode, COUNT(CASE WHEN l_receiptdate > l_commitdate THEN 1 END) * 1.0 / COUNT(*) AS late_shipping_rate FROM lineitem GROUP BY l_shipmode ORDER BY late_shipping_rate DESC LIMIT 1

设计建议

编写详细的 description

description 是 LLM 理解业务语义的核心来源。每个字段应包含业务含义、枚举值(如有)和计算逻辑(如适用)。

    dimensions:
      - name: order_status
        # 好的描述:列出所有可选值及含义
        description: 订单状态。O 表示未完成,F 表示已完成,P 表示部分完成。
        expr: o_orderstatus
        data_type: varchar

合理建模维度、度量和关联

正确区分维度和度量,并定义精确的表关联:

  • 维度(dimensions/time_dimensions):通常出现在 GROUP BY 后的字段,如分类属性、时间字段。

  • Facts → Metrics:先定义原始数值字段为 fact,再基于 fact 定义聚合指标 metric。

  • Relationships:使用 many_to_one 从事实表指向维度表,仅包含实际需要的关联。

使用 filters 封装常见条件

将频繁使用的过滤条件定义为 filters,LLM 在接收到对应的业务术语时可以直接应用。

    filters:
      - name: completed_only
        description: 仅包含已完成的订单行
        expr: l_linestatus = 'F'
      - name: high_value_orders
        description: 高价值订单,订单金额超过 10000
        expr: o_totalprice > 10000

按分析主题拆分,持续迭代

每个 Semantic View 聚焦一个分析主题(如"销售分析""供应链分析"),避免在单个视图中包含过多不相关的表。内部技术字段(分区键、审计字段)不需要暴露。

使用 CREATE OR REPLACE 持续优化:根据实际 NL2SQL 的错误模式,补充 description、添加 filters 或调整 metrics 定义。

使用限制

限制项

说明

功能状态

当前处于内测阶段,功能和语法可能在正式发布时调整。

YAML 语法

YAML 格式对缩进敏感,请确保缩进正确。

metrics 表达式

expr 必须是合法的 SQL 聚合表达式,引用的列名需与物理表列名一致。

表引用

base_table 中引用的 schema 和 table 必须在当前集群中存在。