写点什么

如何缓存存储过程的结果

  • 2014-03-31
  • 本文字数:1332 字

    阅读完需:约 4 分钟

Brent Ozar 是咨询公司 Brent Ozar Unlimited 的创始人和负责人,同时也是一名微软最有价值专家和 SQL Server DBA。他发表了一篇博文,介绍一种缓存存储过程结果的方案及应用场景。

在文章开头,他给出了这样一个场景:一家在线商店需要在每个物品的页面上显示用户买过的相关产品。他认为,在完美的世界中,这些数据应该在 Web/ 应用层缓存。但是,有时候,开发人员会构建存储过程来获取这类数据,而最终存储过程的调用过于频繁。

Brent 指出,对于这种已经使用了存储过程的情况,可以构建一个缓存供存储过程使用。

假如加入缓存层之前的代码如下:

复制代码
CREATE PROCEDURE dbo.usp_GetRelatedItems
@ItemID INT AS
BEGIN
SELECT RelatedItemID,RelatedItemName
FROM dbo.BigComplicatedView
WHERE SoldItemID=@ItemID;
END
GO

代码一:原来的存储过程

则加入缓存层之后的代码如下:

复制代码
CREATE PROCEDURE dbo.usp_GetRelatedItems
@ItemID INT AS
BEGIN
IF EXISTS(SELECT * FROM Cache.dbo.GetRelatedItems
WHERE ItemID=@ItemID)
SELECT *
FROM Cache.dbo.GetRelatedItems
WHERE ItemID=@ItemID
ELSE
SELECT RelatedItemID,RelatedItemName
FROM dbo.BigComplicatedView
WHERE SoldItemID=@ItemID;
END
GO

代码二:实现缓存(一)

代码二引入了一个新表 Cache.dbo.GetRelatedItems,其中 Cache 是新建的数据库。该表中的列比 usp_GetRelatedItems 的返回结果多了一个输入字段和一个 ID,其格式如下:

该表中的数据可以根据需要每天晚上或者每周进行一次 truncate。另外,在实际工作中实现这样一个方案时,他还会根据大量 A/B 性能测试的结果创建恰当的聚簇索引。

代码二并未对缓存表进行操作。如果数据没有缓存,其实需要将其插入缓存表,代码如下:

复制代码
CREATE PROCEDURE dbo.usp_GetRelatedItems
@ItemID INT AS
BEGIN
/* 查看待查找的记录是否已经缓存 */
IF NOT EXISTS(SELECT * FROM Cache.dbo.GetRelatedItems
WHERE ItemID=@ItemID)
BEGIN
/* 缓存中没有记录,因此插入缓存 */
INSERT INTO Cache.dbo.GetRelatedItems
(ItemID,RelatedItemID,RelatedItemName)
SELECT RelatedItemID,RelatedItemName
FROM dbo.BigComplicatedView
WHERE SoldItemID=@ItemID;
END
/* 从缓存中获取记录 */
SELECT *
FROM Cache.dbo.GetRelatedItems
WHERE ItemID=@ItemID
END
GO

代码三:实现缓存(二)

他承认,这种做法会增加 SQL Server 的写负载,但他只有在面临下面这些情况时才使用这种方案:

  • 操作极为密集但只读的存储过程
  • 调用非常频繁(每分钟几百或几千次)
  • 其结果变化频率少于每天一次(或者不关心实时精度)
  • 业务需要非常快的系统改进速度,没有时间等着开发人员实现一个缓存层

最后,他指出,这只是紧急情况下让业务恢复运行的一种创可贴式方案。另外,他还推荐了一些与缓存相关的资源,包括最快的查询是不用执行的那个选择缓存方式通过缓存让系统更好地运行。有兴趣的读者可以进一步阅读。


感谢包研对本文的审校。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ )或者腾讯微博( @InfoQ )关注我们,并与我们的编辑和其他读者朋友交流。

2014-03-31 07:501868
用户头像

发布了 256 篇内容, 共 91.5 次阅读, 收获喜欢 12 次。

关注

评论

发布
暂无评论
发现更多内容

「前端组件化」以Antd为例,快速打通UI组件开发的任督二脉

叶一一

前端 React 10月月更

SAP | 认识 abap 工作台(下)

暮春零贰

SAP abap 10月月更

VS2019 添加bits/stdc++.h万能头文件库

Yeats_Liao

后端 Java core 10月月更

微信红包系统设计分享 | 如何扛住100亿次请求?

Johnny

Java面向对象之方法块+this关键字

魏铁锤

10月月更

List的基础数据的处理

卢卡多多

List 10月月更

「Hive进阶篇」四、HQL 高级巧用

大数据阶梯之路

大数据 hive 面试

IDEA SpringBoot SQL连接常见五大异常处理

Yeats_Liao

后端 Java core 10月月更

还在为sql注入眼花缭乱的过滤而烦恼?一文教您快速找出所有过滤内容

贤鱼很忙

网络安全 SQL注入 10月月更

微信红包体系设计分析

Johnny

全链路监控建设的4个重点

穿过生命散发芬芳

全链路监控 10月月更

「经验总结」高效开发,老代码可以这样动

叶一一

高效工作 前端 10月月更

「CSS畅想」我的发呆专属,反复解锁手机屏幕

叶一一

CSS JavaScript 前端 10月月更

「CSS畅想」自动打字效果,默写首诗来读读

叶一一

JavaScript 前端 10月月更

「CSS畅想」定时+随机,开启今日上上签

叶一一

JavaScript 前端 10月月更

Dev-C++5.11安装教程

Yeats_Liao

后端 Java core 10月月更

微信红包实现原理

Johnny

Java面向对象之构造方法

魏铁锤

10月月更

cstdio的源码学习分析10-格式化输入输出函数fprintf---宏定义/辅助函数分析02

桑榆

源码刨析 10月月更 C++

容量管理的三个层次

阿泽🧸

10月月更 容量管理

微信红包后台系统可用性设计实践

Johnny

将系统划分为模块(微服务)的必要性

宇宙之一粟

微服务 系统设计 论文阅读 模块化 10月月更

从手动测试到自动化测试(下)

FunTester

「小程序开发」关于网页与小程序的通信

叶一一

前端 小程序开发 10月月更

【愚公系列】2022年10月 Go教学课程 028-函数小结案例(通讯录)

愚公搬代码

10月月更

层出不穷的机器学习框架到底在“卷”什么?

小红书技术REDtech

机器学习

「Hive进阶篇」三、HQL底层执行过程及原理详解

大数据阶梯之路

大数据 hive 面试 数仓

一文彻底搞懂IP地址到底是什么?

長歌

面向对象之方法重载

魏铁锤

10月月更

「React开发」梳理HOC的点点滴滴

叶一一

前端 React 10月月更

「前端组件开发」越折腾越有趣,封装了一个表单组件

叶一一

前端 React 组件开发 10月月更

如何缓存存储过程的结果_语言 & 开发_马德奎_InfoQ精选文章