你的位置:首页 > 数据库

[数据库]为什么我还不推荐内存中OLTP给用户


嗯,有些人在看玩这篇文章后会恨我,但我还是要说。1个月来我在内存中OLTP这个里领域里做了大量的工作,很多用户都请求使用这个惊艳的新技术。遗憾的是,关于内存中OLTP没有一个是真的令人激动的——看完你就知道了。

内存中OLTP有问题么?

没有!真的!我喜欢这个惊艳的新技术,但我还不能推荐它给任何用户。就这样!很有用户现在还运行在SQL Server 2008(R2)上,他们就想迁移到SQL Server 2014上。这个惊艳新技术给他们100倍的吞吐量提升。因此让我们来用它吧!遗憾的是并不简单。

很多人都问对于他们的工作量和环境,切换到SQL Server 2014是否有意义。基于我的建议,他们会做出持续至少5年的决定。因此这里我有巨大的责任。我要确保不会建议不能100%融入他们环境的技术。遗憾的是内存中OLTP不能融入99%的所有环境。

因此内存中OLTP有问题么,是什么我还不能推荐它给用户呢?我们开始分析……

没有外键

当微软首次向公众展示内存中OLTP时,它是很惊艳的:你切换开关,然后你的工作吞吐量就会快100倍。你只记住了立即走向右手边的针,不是么?但事实完全不一样。假设你有一个现存的数据库,你想要移动它的一些表到内存中OLTP。

这是不行的,因为内存中OLTP当前不支持外键(foreign keys)。非常希望你的数据库设计有引用完整性(referential integrity)。如果不是的话,请回到数据库基础设计,了解下引用完整性。这已是很多用户已经经历的最常见中断切换之一。他们喜欢迁移一些表到内存中OLTP,但他们不喜欢用它来丢失他们的引用完整性……

不能修改数据库架构

现在假设你同意在自己的表上不使用外键,你已经迁移它们到内存中OLTP。到目前还好。在你的内存优化表上如何处理架构修改呢?任何ALTER TABLE语句不被支持,你不能稍后创建任何额外可能需要的索引(哈希或范围索引)。当创建1个哈希索引,在表创建期间,你需要指定桶数。

这意味着你需要保护你的数据增长,还有随着时间过去你的数据如何改变。当你以后想要修改你的哈希桶数,因为你已意识到你有大量的哈希碰撞,你必须删掉你的内存优化表,然后再次重建。同时你如何处理你的数据?你必须转移它到另一个表,这样的话你不会丢失数据。这时你把数据存在哪里呢?用户如果这时还要访问这些数据怎么办?有很多的问题,但没有真正有用的答案……

没有执行计划

好,现在你用内存优化表很好,现在你想使用存储过程的本地编译功能。哇哦,现在好戏才开始!本地编译存储过程真的,真的非常快,因为你用本地机器码执行——C代码编译成汇编指令!太棒了!但是在查询执行期间是没有执行计划的,因为你只执行汇指令,不再执行那些传统缓慢解释后的执行计划。

当你执行遇到问题时,你怎么办?你不能看实际执行计划来认出问题。SQL Server只提供你估计计划,但估计计划不告诉你任何真实信息。它只是个估计,没别的。你真的想钻研生成的C代码来找出为什么本地编译存储过程这么慢?我不这么认为。

没有重编译

除了没有实际执行计划外,也没有重编译。但你的数据分布改变时,你还是用同样编译的执行计划。在执行期间本地编译存储过程不能重编译。我说过,在运行期间你只执行汇编指令——它们不能被重编译。

你如何摆脱这个问题?删除并重建你的存储过程,因为ALTER PROCEDURE语句不被支持。当你删除你的存储过程,你也会丢失所有授予的安全许可。你真的想丢失它们?另外,你的本地编译存储过程必须用SCHEMABINDING创建。因此当你已经删除存储过程本身时,你才可以删除你的内存优化表(例如,当你想修改哈希桶数时)。偶滴神啊……

本地编译的业务逻辑

这是我喜欢之一:在用本地编译的存储过程里运行复杂的CPU密集的业务逻辑。哇噢,我喜欢你有的那个大钱包!在SQL Server里运行复杂的CPU密集的业务逻辑是你可以有的最昂贵想法之一。在企业版SQL Server里,SQL Server是以每核心7000刀授权。因为我不想在SQL Server里运行任何CPU密集的工作!那一点也不经济。当然从微软角度来说这个很有意义。

如果在SQL Server里你有一些复杂CPU密集的业务逻辑,把它移到应用服务器(例如,Web服务器),因为1个应用服务器授权是完全不同的——非常便宜。你主要会有架构问题,没别的。我从不在SQL Server内部运行业务逻辑。

“对于每个人,640K应该足够了”

哈哈,那是我计算机发展史里最喜欢的名言之一。遗憾的是他说错了,当你看这篇文章时,看看用的电脑硬件时就会发现。当你使用内存中OLTP时,你需要大量的内存。微软建议内存大小为你内存优化表大小的2倍,例如对于150GB大小的表,你需要300GB的内存。另外的内存用做内存中OLTP内存使用的行版本控制。现在假设下,当你删除你的表,同时你想转移数据到另一个内存优化表:在这个情况下你应该有近600GB的内存!准备好了么?

关于OLTP

人们会问我,为什么我对这个惊艳的新技术如此否定。不是的,我并非否定,我只想告诉你事情的2面性,这样的话你可以做出正确的决定。

另外一些人告诉我内存中OLTP如此酷,因为它可以用作ETL过程里的分段表(staging table),并且我们不需要SQL Server里的临时表。哎呦!我们在慢慢拼写下这个技术的名称——非常慢:内存中O-L-T-P!它是关于OLTP——在线事务处理(Online Transaction Processing)。当然在其它场景也可以使用,但主焦点应该是OLTP场景!好好考虑下它。如果你当前有临时表的问题,那就在工作量上下文章,尝试在你临时表上减少工作量的压力。在性能调优里我经常提到:我们的终极目标是解决潜在的问题根源,不是为它创建一个解决方案。(例如当你看到 CXPACKET等待时,设置 MAXDOP为1即可)

小结

内存中OLTP是个惊艳的新技术。但目前只实现了雏形。有太多的限制刚好阻止了大量人们在生产环境中使用它。在这篇文章里我已经概括了这些限制中的部分,这样的话你就可以重新考虑下是否想把内存中OLTP引入你的特定场景。

我很期待在SQL Server里的下个版本再次讨论这个话题,在一个图表里剔除那些无关的条目,因为微软已经移除了这些限制。这个惊艳技术还是由微软来决定往前发展的!

感谢关注!