温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

动态SQL如何做缓存

发布时间:2026-09-29 11:34:34 来源:亿速云 阅读:96 作者:小樊 栏目:数据库

在“动态 SQL 做缓存”这个问题上,需要先明确一点:缓存的对象通常不是“SQL 字符串本身”,而是“SQL 执行结果”或“解析后的 SQL 结构”。下面按常见场景系统讲一下。


一、什么是“动态 SQL”

动态 SQL 一般指:

  • 根据条件拼 SQL(如 MyBatis <if>、<foreach>)
  • 运行时决定表名 / 字段 / 排序
  • 同一方法生成多种 SQL

这类 SQL 不易被传统 SQL 缓存命中,因为:

  • SQL 文本不同
  • 参数不同
  • 条件组合爆炸

二、动态 SQL 的缓存层次

1️⃣ SQL 解析缓存(减少重复解析)

适合:复杂动态 SQL 拼接代价大

做法:

  • 缓存「条件 → SQL 模板」
  • 相同条件直接复用 SQL

示例(伪代码):

String sql = sqlCache.get(conditionKey);
if (sql == null) {
    sql = buildDynamicSql(condition);
    sqlCache.put(conditionKey, sql);
}

✅ 优点:减少字符串拼接 / 解析
❌ 不解决数据一致性问题


2️⃣ 查询结果缓存(最常见)

适合:读多写少、数据变化不频繁

MyBatis 一级 / 二级缓存

<cache/>

注意:

  • 一级缓存:SqlSession 级别
  • 二级缓存:Mapper 级别
  • ❌ 动态 SQL + 不同参数 → 命中率低

手动缓存(推荐)

String cacheKey = buildKey(sql, params);
Object data = redis.get(cacheKey);
if (data == null) {
    data = mapper.query(params);
    redis.set(cacheKey, data, 5min);
}

✅ 命中率高
✅ 可控
❌ 需处理失效


3️⃣ 预编译 SQL 缓存(PreparedStatement)

数据库层天然支持:

  • ? 占位符
  • 相同结构 SQL 复用执行计划

✅ 动态 SQL 应尽量:

WHERE name = ? AND age = ?

而不是:

WHERE name = 'tom' AND age = 18

三、动态 SQL 缓存的关键问题

❗ 1. 缓存 Key 怎么设计

必须包含:

  • SQL 模板
  • 参数值(顺序敏感)
  • 分页 / 排序
  • 租户 ID(多租户系统)
key = md5(sql + params + page + tenant)

❗ 2. 缓存失效策略

常见方案:

  • 写操作清空相关 Key
  • 按表维度失效
  • TTL 兜底
@CacheEvict(value="user", key="#user.id")

❗ 3. 动态 SQL 不适合缓存的情况

❌ 实时性要求高
❌ 数据频繁变化
❌ 结果集很大
❌ 权限敏感(不同人结果不同)


四、最佳实践总结

✅ 动态 SQL 优先缓存结果,而不是 SQL 本身
✅ 用参数化 SQL 提升数据库缓存效率
✅ 手动 Cache(Redis / Caffeine)比框架 Cache 更可控
✅ Key 设计必须“完全决定结果”

如果你用的是 MyBatis / MyBatis-Plus / JPA / 原生 JDBC,我可以给你具体实现示例。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI
助
手