ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

SQLBot数据源导入备注,智能问数更清晰

SQLBot数据源导入备注,智能问数更清晰 实际做智能问数系统时团队经常忽略一个看似不起眼却影响结果质量的环节数据源导入时的备注信息。这里的“备注”不只是给 DBA 看的说明文字而是模型理解业务语义的关键输入。SQLBot 这类智能问数工具接入数据源后真正决定回答质量的不是连接速度而是它能不能读懂每张表、每个字段的业务含义。表名叫user可能是注册用户可能是黑名单用户也可能是登录流水没有备注模型只能靠字段名猜测在复杂库表上猜错的概率几乎是必然的。本文围绕“SQLBot 数据源导入备注智能问数更清晰”这一主题梳理智能问数系统中数据源连接、元数据采集、备注维护和问答下发之间的完整链路并给出多数据源场景下的一套可实现方案。内容覆盖 Spring Boot、MyBatis Plus 动态数据源、ShardingSphere 逻辑数据源注册等常见技术栈。读完可以理解为什么备注比连接信息更影响问答效果也能在自己项目里把数据源接入从“能连上”推进到“问得清”。1. 智能问数系统为什么需要数据源备注1.1 数据源接入只是第一步元数据描述才是问答质量的关键智能问数的处理链路可以简化为用户提问 - 理解意图 - 访问数据源元数据 - 生成 SQL - 执行查询 - 返回答案。传统 BI 工具里数据源接入完成之后报表开发人员还会手动配置维度、度量、层级关系等业务信息。智能问数系统也一样数据源连接只是完成了“数据库可访问”这一步后续生成 SQL 时依赖的是对库表结构的理解。一个只有CREATE TABLE结构的数据库对模型来说缺失业务上下文。字段名叫status值是 0、1、2模型无法判断 0 是“未支付”“禁用”还是“待审核”。字段名叫remark模型更无法区分它记录的是订单备注还是用户自我描述。这些信息不会出现在数据库系统表中只能通过数据源导入备注补全。从工程角度数据源备注可以理解为“连接信息之外的业务元数据”。它通常包括数据源级备注这个库属于哪个业务域、面向什么场景、负责人是谁。表级备注每张表记录的是什么实体主键含义数据更新时间规律。字段级备注每个字段的业务含义、值域枚举、单位、敏感级别。这些备注进入系统后会被拼接到模型提示词、Schema 描述或 SQL 生成上下文中直接影响生成 SQL 的正确性。1.2 没有备注时智能问数会踩哪些坑在真实项目经验里没有备注的系统并不是“偶尔答错”而是在语义模糊的场景下系统性出错。常见现象包括第一同名字段被混淆。数据库里多个表都有create_time字段用户问“本月新增客户有多少”模型可能选中了订单表的create_time统计结果变成“本月新增订单量”。第二枚举值无法解释。字段只有 0 和 1用户问“男性用户占比”模型不知道 0 还是 1 代表男性只能随机猜或者直接报错。第三关联关系缺失。表和表之间没有外键模型靠命名猜测连接字段容易生成笛卡尔积或错误 Join 语句。第四敏感信息没有标识。字段没有备注标注“身份证号”“手机号”时模型可能在展示结果时直接输出明文这已经不是准确性问题而是数据安全问题。场景没有备注时模型的表现有备注时的表现多表存在同名字段随机选中或默认选第一张表按业务范围选择正确字段枚举值字段 status0/1无法推断语义根据备注映射为业务状态表间无外键猜测关联列可能笛卡尔积按备注中的关联说明生成 Join敏感字段结果中输出明文按备注规则脱敏或禁止展示1.3 备注在问数链路中的生效位置备注不是数据库注释本身。虽然可以同步数据库COMMENT但要理解两者的区别。数据库COMMENT存储在数据库元数据中对应用和使用者可见智能问数系统的数据源备注是面向问答引擎的增强元数据除了同步数据库注释还能补充数据库注释里不存在的业务口径、枚举含义和计算说明。在实际链路中备注信息至少有两个生效入口Schema 描述入口模型生成 SQL 前会拿到表结构描述备注被序列化进描述文本帮助模型理解每个字段含义。意图映射入口用户问题中的业务词汇与物理表字段之间做映射时备注提供语义匹配依据。所以数据源导入备注真正影响的是“语义理解”和“SQL 生成”两个环节而不是简单在页面上显示一行说明文字。2. 数据源模型设计从连接信息扩展到业务元数据2.1 基础数据源表结构先看最基础的数据源配置表。在 Spring Boot 项目中数据源配置通常会持久化到数据库动态切换时从配置表读取。CREATE TABLE data_source_config ( id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT 主键, source_code VARCHAR(64) NOT NULL COMMENT 数据源编码唯一标识, source_name VARCHAR(128) NOT NULL COMMENT 数据源名称展示用, db_type VARCHAR(32) NOT NULL COMMENT 数据库类型mysql/oracle/clickhouse等, host VARCHAR(128) NOT NULL, port INT NOT NULL, database_name VARCHAR(128) NOT NULL, username VARCHAR(128) NOT NULL, password VARCHAR(256) NOT NULL COMMENT 密文存储, jdbc_params VARCHAR(512) COMMENT JDBC扩展参数, create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, UNIQUE KEY uk_source_code (source_code) ) COMMENT 数据源连接配置表;这张表解决“怎么连上数据库”的问题。source_code用于在系统内部定位数据源后面动态数据源切换和问答引擎都会依赖它。只到这里还不够。问数系统面对的是业务人员他们不知道source_code是什么也不关心数据库 IP。他们要的是“客户域数据源”“订单域数据源”这样的业务标识。因此需要在连接配置之上增加业务元数据字段。2.2 增加备注与元数据字段后的表结构在基础表上扩展备注字段有两种形态一种是直接在data_source_config上增加字段适合备注简单、层级少的场景另一种是独立出元数据表适合需要细粒度管理表级和字段级备注的场景。独立表设计更灵活。建议至少有三张表数据源基础表、表元数据表、字段元数据表。核心字段如下CREATE TABLE ds_table_meta ( id BIGINT PRIMARY KEY AUTO_INCREMENT, data_source_id BIGINT NOT NULL COMMENT 关联数据源, table_name VARCHAR(128) NOT NULL COMMENT 物理表名, table_comment VARCHAR(512) COMMENT 表备注业务含义、主实体、更新规律, biz_domain VARCHAR(64) COMMENT 业务域客户/订单/商品/库存等, table_level ENUM(FACT,DIMENSION,SUMMARY,OTHER) DEFAULT OTHER, owner VARCHAR(64) COMMENT 负责人, related_info VARCHAR(1024) COMMENT 关联说明例如本表与订单表通过 order_id 关联, remark_status TINYINT DEFAULT 1 COMMENT 1-已完善 0-待完善, import_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ) COMMENT 表级业务元数据; CREATE TABLE ds_field_meta ( id BIGINT PRIMARY KEY AUTO_INCREMENT, data_source_id BIGINT NOT NULL, table_name VARCHAR(128) NOT NULL, field_name VARCHAR(128) NOT NULL COMMENT 物理字段名, field_comment VARCHAR(512) COMMENT 字段业务含义, value_type VARCHAR(64) COMMENT 数值类型金额/百分比/数量等, enum_values VARCHAR(1024) COMMENT 枚举值映射如 0-未支付,1-已支付,2-已退款, unit VARCHAR(32) COMMENT 单位元/万/条/人等, sensitive ENUM(NONE,MASK,FORBIDDEN) DEFAULT NONE, formula VARCHAR(512) COMMENT 口径公式或计算说明, is_primary_key TINYINT DEFAULT 0, update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ) COMMENT 字段级业务元数据;为什么拆表而不直接合并因为表级备注和字段级备注的维护频率、更新方、同步逻辑不同。字段级备注数量庞大一张宽表存所有字段会导致数据冗余和更新冲突。拆表后还可以针对不同表做批量导入、批量更新和权限控制。注意不要把所有备注塞进data_source_config的remark字段里。单字段无法表达表级、字段级和值域信息后期解析、检索、提示词组装都会很痛苦。2.3 备注信息的三种来源数据源导入时备注可以从三个渠道进入系统第一是数据库注释自动同步。大多数数据库支持COMMENT导入数据源成功后通过 JDBC 的DatabaseMetaData读取表注释和字段注释写入元数据表。这一部分零成本但覆盖面有限。DatabaseMetaData metaData connection.getMetaData(); ResultSet tables metaData.getTables(catalog, schema, %, new String[]{TABLE}); while (tables.next()) { String tableName tables.getString(TABLE_NAME); String tableComment tables.getString(REMARKS); // 写入 ds_table_meta }第二是人工补充。自动同步完成后在管理页面上按表、按字段补充业务口径。人工补充的内容质量最高但成本也高建议优先补充被高频查询的核心表和枚举字段。第三是 AI 辅助生成。把表结构信息发送给大模型让模型根据表名、字段名、已有注释生成更完整的业务说明再由人工确认。这个方式适合数据源表数量多、人工维护不过来时的首轮导入。3. 多数据源场景下的导入与存储实践3.1 问数系统为什么天然是多数据源架构智能问数系统很少只连一个库。常见情况是不同业务域使用不同数据库MySQL 存交易数据ClickHouse 存分析数据Redis 存实时指标甚至同一个 MySQL 实例里做了分库分表。用户不会关心数据分散在哪他们只会问“这个月销售额是多少”系统需要知道该去哪个数据源执行。多数据源架构下数据源注册、切换、路由是基础能力。Spring Boot 生态中比较常用的方案是dynamic-datasource-spring-boot-starter它基于DataSource抽象和 AOP 实现运行时数据源切换可以把多个数据源配置统一管理。关于 MyBatis Plus 多数据源的常见做法是在配置文件中声明多个数据源spring: datasource: dynamic: primary: master strict: true datasource: master: url: jdbc:mysql://localhost:3306/biz_master username: root password: ${DB_PASSWORD} driver-class-name: com.mysql.cj.jdbc.Driver analysis: url: jdbc:clickhouse://localhost:8123/biz_analysis username: default password: ${CH_PASSWORD} driver-class-name: com.clickhouse.jdbc.ClickHouseDriver真实生产环境不要把密码直接写在配置里可以通过环境变量或配置中心注入。primary: master表示默认走主数据源strict: true表示未匹配到指定数据源时直接报错避免静默走错库。3.2 动态数据源注册与切换原理dynamic-datasource的核心是维护一个DataSource路由表。每次请求通过DataSourceContextHolder设置当前线程要用的数据源 keyDynamicRoutingDataSource根据 key 从路由表中取出对应DataSource。// 切换数据源的常用方式 DS(analysis) public ListMapString, Object queryAnalysisData(String sql) { return jdbcTemplate.queryForList(sql); }DS注解本质上是切面编程在执行方法前把 key 设置到ThreadLocal方法结束后清理。这种方式适合业务代码中显式选择数据源。对于智能问数系统SQL 是从自然语言动态生成的编译期根本不知道会命中哪个数据源所以不能依赖DS注解写死路由。更合理的做法是解析问题时先定位目标数据源 key然后直接通过DynamicRoutingDataSource获取指定DataSource执行 SQL。Autowired private DynamicRoutingDataSource dynamicRoutingDataSource; public ListMapString, Object executeOnDataSource(String sourceCode, String sql) { DataSource dataSource dynamicRoutingDataSource.getDataSource(sourceCode); try (Connection connection dataSource.getConnection(); Statement statement connection.createStatement(); ResultSet rs statement.executeQuery(sql)) { return resultSetToMaps(rs); } }这样就把“数据源选择”从方法级注解变成了运行期根据用户问题动态决策更贴合智能问数的场景。3.3 将 ShardingSphere 数据源注册进动态数据源有些系统已经用了 ShardingSphere 做分库分表此时数据库层面不是一个普通DataSource而是一个由 ShardingSphere 构造的逻辑数据源。要让它接入动态数据源体系需要把 ShardingSphere 创建好的DataSource对象注册到DynamicRoutingDataSource的路由表中。思路如下加载 ShardingSphere 配置构建逻辑数据源再通过dynamicRoutingDataSource.addDataSource(key, shardingSphereDataSource)注册。Configuration public class ShardingDataSourceRegistrar { Autowired private DynamicRoutingDataSource dynamicRoutingDataSource; PostConstruct public void register() throws Exception { // 从配置中心获取 ShardingSphere 配置实际项目建议使用持久化配置源 MapString, DataSource dataSourceMap buildActualDataSources(); // 构造 ShardingSphere 逻辑数据源 ShardingSphereDataSource shardingDataSource ShardingSphereDataSourceFactory.createDataSource( dataSourceMap, new Properties(), buildShardingRules() ); // 注册到动态数据源路由表 dynamicRoutingDataSource.addDataSource(sharding_order, shardingDataSource); } }这里的关键是注册时机。PostConstruct在 Spring 容器初始化阶段执行如果动态数据源对象尚未完全初始化可能出现空引用。稳妥做法是监听ApplicationReadyEvent确保容器启动完成后再注册。Component public class ShardingDataSourceInitializer implements ApplicationListenerApplicationReadyEvent { Override public void onApplicationEvent(ApplicationReadyEvent event) { // 容器就绪后注册避免依赖未初始化完成 registerShardingDataSource(); } }注册完成之后智能问数系统只需把 ShardingSphere 逻辑数据源当作普通数据源使用SQL 下发时自然走分库分表规则。注意分片规则和元数据备注要分开管理分片规则属于物理路由元数据备注属于语义理解两者不要混在一个配置里。3.4 导入数据源时同步写入备注信息数据源导入接口是备注信息进入系统的第一入口。一个合理的接口设计应当同时完成四件事校验连接参数、写入基础配置、同步数据库注释、生成待完善备注任务。PostMapping(/data-source/import) public DataSourceImportResult importDataSource(RequestBody DataSourceImportDTO dto) { // 1. 校验连接连通性 connectionValidator.validate(dto); // 2. 持久化连接配置 Long dataSourceId dataSourceConfigService.save(dto); // 3. 读取数据库注释并写入元数据表 metadataSyncService.syncTableAndFieldMeta(dataSourceId, dto.getConnectionInfo()); // 4. 收集备注缺口生成待完善任务 ListMetaGap gaps metadataSyncService.findGaps(dataSourceId); remarkTaskService.createTasks(dataSourceId, gaps); return DataSourceImportResult.success(dataSourceId, gaps.size()); }这里的第四步很关键。所谓“生成待完善任务”是把没有备注或备注为空的核心表、核心字段识别出来进入人工或 AI 补全流程。如果没有这一步元数据表里只会有一堆从数据库同步来的REMARK业务口径仍然缺失。同步数据库注释时有一个常见问题MySQL 的information_schema.TABLES.TABLE_COMMENT和information_schema.COLUMNS.COLUMN_COMMENT能拿到注释但不同数据库的元数据 API 差异很大。建议在代码里封装一个MetadataAdapter接口按数据库类型实现不同逻辑避免 Service 层堆满if (dbType.equals(mysql))这样的判断。4. 备注信息如何在智能问答中生效4.1 把备注组装进模型提示词智能问数的 SQL 生成通常依赖大模型。模型能读到的信息不应该是原始建表语句而应该是经过整理的 Schema 描述其中包含表备注、字段备注、枚举值。这是数据源导入备注真正产生价值的地方。请根据下面的数据库元数据将用户问题转换为 SQL。 数据源客户域主库 表customer - id: 客户ID主键自增 - name: 客户姓名字符串 - status: 客户状态枚举 0-未激活,1-正常,2-冻结,3-注销 - source_channel: 客户来源枚举 1-自然注册,2-广告投放,3-线下导入 - created_at: 创建时间datetime代表客户首次注册时间 用户问题这个月通过广告投放进来的有效客户有多少对比没有备注的版本模型只能看到id、name、status、source_channel、created_at它无法确定status1是“有效”也无法确定“广告投放”映射到source_channel2。备注的加入让这些问题变得可解。组装提示词时要注意上下文长度。字段多的表不能全量塞进去需要先做一次字段裁剪只保留与用户问题语义相关的字段降低模型误选概率也能减少 Token 消耗。4.2 同名表和字段的冲突消解多数据源场景下冲突比单库更严重。不同数据源里可能有同名表user一个在“客户域”一个在“员工域”。如果提示词只是把两张表都放进去模型很可能生成错误 SQL。常见处理方式有三种第一数据源前缀隔离。提示词中明确标注数据源名称和业务域例如【客户域数据源 / customer 表】让模型感知上下文归属。第二根据问题中的业务词汇预选数据源。先做关键词分类命中某个业务域再加载该域的 Schema而不是全量加载。第三在同名冲突时提示模型需要二次确认。如果用户问题无法唯一确定数据源返回候选列表让用户选择而不是让模型猜。4.3 效果验证对比有无备注的生成结果备注是否有效不能靠感觉要用同一组测试用例对比验证。推荐建立一组覆盖典型语义问题的回归用例分别用“无备注版本”和“有备注版本”跑一遍对比生成 SQL 的正确性。测试问题无备注生成的 SQL有备注生成的 SQL是否合理本月新增有效客户数SELECT COUNT(*) FROM customer无法表达“有效”SELECT COUNT(*) FROM customer WHERE status1 AND created_at 本月起始合理广告渠道客户占比source_channel语义不明可能选错字段WHERE source_channel2映射正确合理两表关联查订单金额Join 条件猜测出错根据 related_info 使用明确关联列合理这份对比结果既用于验证备注配置也可以作为数据源从“已导入”升级为“已完善”的验收标准。5. 数据源导入备注的完整实现示例5.1 项目结构与依赖以一个 Spring Boot 3 项目为例核心依赖如下dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version3.5.5/version /dependency dependency groupIdcom.baomidou/groupId artifactIddynamic-datasource-spring-boot-starter/artifactId version4.3.0/version /dependency dependency groupIdmysql/groupId artifactIdmysql-connector-j/artifactId /dependency注意dynamic-datasource-spring-boot-starter的版本要和 Spring Boot 版本匹配4.x 在不同版本上覆盖范围有差异。落地前先确认当前项目的 Spring Boot 版本再确定 starter 版本不能直接照抄。5.2 数据源导入服务实现下面是一个简化的数据源导入服务包含连接校验、配置保存和元数据同步。Service public class DataSourceImportService { private final DataSourceConfigMapper configMapper; private final TableMetaMapper tableMetaMapper; private final FieldMetaMapper fieldMetaMapper; private final DataSourceConnectionValidator validator; Transactional(rollbackFor Exception.class) public DataSourceImportResult importDataSource(DataSourceImportDTO dto) { // 连接校验不通过直接抛异常 validator.validate(dto.getJdbcUrl(), dto.getUsername(), dto.getPassword()); // 保存基础配置 DataSourceConfig config new DataSourceConfig(); config.setSourceCode(dto.getSourceCode()); config.setSourceName(dto.getSourceName()); config.setDbType(dto.getDbType()); config.setHost(dto.getHost()); config.setPort(dto.getPort()); config.setDatabaseName(dto.getDatabaseName()); config.setUsername(dto.getUsername()); config.setPassword(encrypt(dto.getPassword())); configMapper.insert(config); // 同步数据库注释 syncMetadata(config); return DataSourceImportResult.builder() .dataSourceId(config.getId()) .sourceCode(config.getSourceCode()) .message(数据源导入成功备注信息已同步) .build(); } private void syncMetadata(DataSourceConfig config) { try (Connection connection DriverManager.getConnection( buildJdbcUrl(config), config.getUsername(), decrypt(config.getPassword()))) { DatabaseMetaData metaData connection.getMetaData(); try (ResultSet tables metaData.getTables(connection.getCatalog(), null, %, new String[]{TABLE})) { while (tables.next()) { String tableName tables.getString(TABLE_NAME); String tableComment tables.getString(REMARKS); TableMeta tableMeta new TableMeta(); tableMeta.setDataSourceId(config.getId()); tableMeta.setTableName(tableName); tableMeta.setTableComment(tableComment null ? : tableComment); tableMetaMapper.insert(tableMeta); syncFieldMeta(connection, metaData, config, tableName); } } } catch (SQLException e) { throw new DataSourceImportException(元数据同步失败: e.getMessage(), e); } } private void syncFieldMeta(Connection connection, DatabaseMetaData metaData, DataSourceConfig config, String tableName) { try (ResultSet columns metaData.getColumns(connection.getCatalog(), null, tableName, %)) { while (columns.next()) { String fieldName columns.getString(COLUMN_NAME); String fieldComment columns.getString(REMARKS); FieldMeta fieldMeta new FieldMeta(); fieldMeta.setDataSourceId(config.getId()); fieldMeta.setTableName(tableName); fieldMeta.setFieldName(fieldName); fieldMeta.setFieldComment(fieldComment null ? : fieldComment); fieldMetaMapper.insert(fieldMeta); } } catch (SQLException e) { throw new DataSourceImportException(字段元数据同步失败: tableName, e); } } }这段代码里有几个细节值得注意。第一Transactional保证连接配置和元数据同步要么同时成功要么同时回滚避免出现“数据源已导入但元数据为空”的脏状态。第二元数据同步放在 DriverManager 原始连接层而不是DataSource因为导入阶段还没注册到这个数据源直接用动态数据源反而绕弯。第三密码加解密必须使用成熟算法不能把 Base64 当加密用生产环境建议使用独立密钥服务。实际项目中单实例表数量较多时全量同步getColumns性能不好。可以考虑分批同步或者只在导入时同步表级备注字段级备注按需异步采集。5.3 备注维护接口导入完成只是起点备注需要持续维护。至少提供三个操作更新表备注、更新字段备注、批量导入备注文件。PutMapping(/data-source/{dataSourceId}/table-meta) public void updateTableMeta(PathVariable Long dataSourceId, RequestBody TableMetaUpdateDTO dto) { tableMetaService.updateRemark(dataSourceId, dto.getTableName(), dto.getTableComment()); } PutMapping(/data-source/{dataSourceId}/field-meta) public void updateFieldMeta(PathVariable Long dataSourceId, RequestBody FieldMetaUpdateDTO dto) { fieldMetaService.updateRemark(dataSourceId, dto.getTableName(), dto.getFieldName(), dto.getFieldComment()); } PostMapping(/data-source/{dataSourceId}/remark/import) public void importRemarkFile(PathVariable Long dataSourceId, RequestParam(file) MultipartFile file) { remarkImportService.importExcel(dataSourceId, file); }批量导入文件一般用 Excel格式建议是固定列表名、字段名、字段备注、枚举值、单位、敏感级别。这样可以方便数据仓库团队批量维护也便于版本对比。5.4 验证导入结果启动项目后按下面序列验证调用导入接口传入一个测试 MySQL 数据源。查询ds_table_meta和ds_field_meta确认表注释和字段注释已经写入。调用备注更新接口手工修改某个枚举字段的备注。用一条本来会产生歧义的问题测试智能问答对比修改前后生成的 SQL。正常结果应该是导入后元数据表有数据修改备注后问数结果变化且更符合预期。6. 常见问题与排查路径6.1 问题排查顺序数据源导入备注相关的问题建议按这个顺序排查连接字符串是否可访问账号是否有读取元数据权限。元数据同步是否走了正确的数据库类型适配。表名、字段名大小写是否被数据库处理过同步结果是否为空。备注是否写入了正确的data_source_id是否出现多数据源串线。问答引擎是否真的把备注加载进了提示词而不是只存不读。提示词构建时字段裁剪是否把关键字段过滤掉了。这里最隐蔽的是第 6 条。很多系统备注存了、表也维护了但问答效果没有提升最后发现是提示词组装时只放入了前 N 个字段被裁剪掉的恰好是带有备注的核心字段。因此调试时要能打印出实际发给模型的 Schema 片段。6.2 典型问题汇总下表整理导入备注过程中最容易遇到的问题和处置方式问题现象常见原因检查方式处理建议元数据同步后表名全为空账号没有读取元数据权限或大小写过滤条件写错打印同步日志检查数据库账号权限确认只读权限和元数据访问权限数据库注释读到但中文乱码JDBC URL 缺少字符集参数检查连接串是否带characterEncodingutf8在 JDBC 参数中显式指定字符集备注已更新但问答没变化问答引擎读取的是缓存中的旧 Schema检查 Redis 缓存或本地缓存 TTL备注更新时同步触发 Schema 缓存刷新数据源很多时同步非常慢逐表逐字段同步导致大量往返查询观察同步耗时和 SQL 数量改为批量读取或异步同步ShardingSphere 数据源注册后路由不生效注册顺序早于分片规则初始化打印逻辑数据源中的规则推迟到ApplicationReadyEvent后再注册问题命中错误数据源数据源级备注未作为提示词上下文检查提示词是否包含数据源业务域描述在提示词中拼接数据源备注和业务域6.3 如何确认备注已进入问答上下文让问题“能查出来”不等于回答正确更不等于备注生效。要确认备注进入上下文最好的方式是增加一个调试接口返回实际发送给模型的 Schema 内容GET /api/debug/schema?sourceCodecustomer返回结果里包含表备注、字段备注、枚举值映射。如果这些内容缺失说明问题在元数据装配层如果内容完整但 SQL 仍然错误说明问题在模型推理层需要用更清晰的备注描述或更充分的示例。7. 学习环境与生产环境的差异7.1 环境对照表数据源导入备注在本地跑通很容易但进入生产环境还需要补齐很多能力维度本地学习环境生产环境数据源密码配置文件明文或环境变量配置中心加密存储使用密钥管理服务数据库权限直接用 root/管理员账号最小权限账号仅授予查询和元数据读取元数据同步方式同步一次性执行异步任务支持增量同步和失败重试备注审核直接写入需要审核流程尤其涉及敏感字段缓存刷新手动重启刷新备注变更消息通知问答引擎刷新 Schema安全要求不关注敏感字段脱敏、操作审计、数据源访问白名单回滚能力不关注元数据支持版本回滚错误备注可恢复7.2 生产环境的关键保障生产环境里备注信息变成了影响 SQL 生成质量的重要资产因此要按资产管理对待。第一敏感字段治理优先于备注完善。在导入备注时如果发现身份证、手机号、银行卡号等字段没有敏感级别应该先标记默认脱敏再由人工确认。不要等备注完全完善后才做脱敏。第二备注变更要有版本。业务口径会变比如status2之前代表冻结后来改为注销。如果没有版本记录换一个数据源或回滚配置时无法追溯。建议在ds_field_meta上增加version字段更新时保留历史版本。第三备注与数据库注释的一致性检查。如果建表语句发生变更新增字段没有备注应该通过定时任务扫描发现元数据缺口并生成待完善任务而不是等用户问错之后才被动发现。8. 最佳实践与扩展方向8.1 数据源备注维护清单在项目迭代过程中可以沉淀一份适用于团队内部的数据源备注检查清单[ ] 每个数据源是否配置了业务域说明和负责人。[ ] 核心表是否都维护了表级备注是否
返回列表