10 月 23 - 25 日,QCon 上海站即将召开,现在购票,享9折优惠 了解详情
写点什么

如何缓存存储过程的结果

  • 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:502055
用户头像

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

关注

评论

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

滴滴前端二面vue相关面试题

bb_xiaxia1998

Vue

你了解Redis RDB快照吗

芥末拌个饭吧

redis 后端 10月月更

使用less/css 动态的切换主题色实现换肤功能

默默的成长

前端 Vue 3 10月月更

Java三大特性(三)—多态

共饮一杯无

Java 多态 10月月更

嵌入式Linux下移植MT7601无线WIFI(网卡)驱动

DS小龙哥

10月月更

React面试八股文(第一期)

beifeng1996

React

最大为 N 的数字组合

掘金安东尼

算法 10月月更

PriorityQueue 源码解析(四)

知识浅谈

Queue 10月月更

pandas如何读写源数据

芥末拌个饭吧

pandas python 3.5+ 10月月更

软件测试 | 测试开发 | 一文搞定 Appium 环境配置

测吧(北京)科技有限公司

测试

华为云从入门到实战 | 云容器服务

TiAmo

华为 华为云 云开发 10月月更

React源码分析(三):useState,useReducer

goClient1992

React

new Vue的时候到底做了什么

bb_xiaxia1998

Vue

深入浅出防抖与节流函数

CoderBin

JavaScript 面试 前端 防抖节流 10月月更

SparkSQL on K8s 在网易传媒的落地实践

网易数帆

大数据 spark Kubernetes Kyuubi 企业号十月 PK 榜

C++ | bool变量值在程序运行过程中自动篡改问题解决

中国好公民st

c++ 变量 10月月更

Vue的computed和watch的区别是什么?

bb_xiaxia1998

Vue

软件测试 | 测试开发 | Cypress 强大全新的 Web UI 测试框架应用尝鲜

测吧(北京)科技有限公司

测试

React循环DOM时为什么需要添加key

beifeng1996

React

算法基础(六)| 双指针算法及模板应用

timerring

算法 双指针 10月月更

你真的了解redis持久化机制AOF吗?

芥末拌个饭吧

redis 后端 10月月更

linux下驱动开发_红外线解码驱动

DS小龙哥

10月月更

react源码中的生命周期和事件系统

flyzz177

React

2022昇腾AI创新大赛16地区域决赛圆满落幕 32支队伍角逐全国冠军

极客天地

React的useLayoutEffect和useEffect执行时机有什么不同

beifeng1996

React

React源码分析(二)渲染机制

goClient1992

React

vivo平台化实践探索之旅-平台产品系列01

vivo互联网技术

平台化 系统平台化

NFT链游系统开发丨Alien Worlds异形世界链游系统开发成熟技术(Demo)

I8O28578624

页面中元素的吸顶

默默的成长

前端 Vue 3 10月月更

页面中元素的锚点定位

默默的成长

前端 Vue 3 10月月更

从react源码看hooks的原理

flyzz177

React

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