2011-12-19 33 views
11

事实上,如果我从我的应用程序调用存储过程,我需要连接到我的数据库。为什么执行存储过程比脚本中的SQL查询更快?

那么,为什么调用“存储过程”应该比“传递SQL查询”字符串要执行更快?

+8

真的是没有太多的存储过程的速度优势了,这些天。正确的参数化查询将与存储过程一样高效。单凭这一点不是使用存储过程 – 2011-12-19 09:51:41

回答

40

SQL服务器基本上会经过以下步骤执行任何查询(存储过程调用或即席SQL语句):

1)语法检查查询
2)如果是好的 - 它会检查计划缓存以查看它是否已经有针对该查询的执行计划
3)如果有执行计划 - 该计划被(重新)使用并且执行查询
4)如果还没有计划,执行计划确定
5)该计划存储在计划缓存中供以后重新使用
6)执行查询

的一点是:即席SQL和存储过程是treatly 没有区别

如果一个特设的SQL查询是否正确使用参数 - 因为它应该无论如何,以防止SQL注入攻击 - 它的性能并没有什么不同,最肯定不超过执行一个存储过程更糟

存储过程有其他的好处(无需授予用户直接访问表,例如),但在性能方面,采用适当的参数化即席SQL查询是一样高效如使用存储过程。

更新:使用存储过程非参数化查询是更好的原因主要有两个:

  • ,因为每一个非参数化查询是新的,不同的查询到SQL Server,它必须经历确定每个查询的执行计划的所有步骤(从而浪费时间 - 并且浪费计划缓存空间,因为将执行计划存储到计划缓存中并不真的有助于最终,因为该特定查询可能会而不是再次执行)

  • 非参数化查询是在SQL注入攻击的风险,应不惜一切代价

+0

P.S. SP存储/缓存...但例如,如果我有一个“where”子句,我从客户端传递一个自定义值,它应该与该输入/条件编译;所以每个参数都有专用的SP? – markzzz 2011-12-19 10:19:24

+1

@markzzz:不,在这种情况下,我会向存储过程的定义(要从调用者传递)添加一个参数,并在存储过程的“主体”中使用该参数。这样,再次,你有一个**存储proc主体,**一个**(缓存)的执行计划,你可以用任何可能的值调用它。 – 2011-12-19 11:39:46

+0

@marc_s:非参数化查询如何处于sql注入风险中,因为非参数化查询永远不会接受任何参数。让我知道我是否有错 – 2014-03-14 07:38:19

2

存储过程被编译和缓存。但是,SQL语句将与现有的执行计划进行比较,如果使用了匹配项,则会使某些优势无效。

多次执行后的实际性能差异是多少?

+0

的好理由?这是什么意思?结果被缓存或只是SQL查询? – markzzz 2011-12-19 09:48:37

+1

我喜欢得到真实的答案。 – NimChimpsky 2011-12-19 09:55:07

+0

@marc_s我还在写答案。我想我应该知道规则。丛林法则等等。而且,一个sql查询只会在第一次运行后执行计划存在时才会与sproc相同,而不像正在创建的sproc。 – NimChimpsky 2011-12-19 10:01:30

5

因为每次将查询字符串传递给SQL Server时,代码都必须进行编译等,因此存储过程已经编译并准备在服务器上运行。

此外,您通过网络发送的数据较少,尽管这通常影响最小。

编辑: 作为备注存储过程有其他好处。

1)安全性 - 因为实际的查询存储你不通过,这意味着任何人拦截网络流量不会获得任何洞察到你的表结构的网络传输该服务器上。另外一个精心设计的SP可以防止注入攻击。

2)代码分离 - ,你把你的数据库的代码在你的数据库和应用程序中的应用程序代码中,很少有交叉,我发现这使得bug修复要好很多。

3)可维护性和代码重用,您可以重复使用一个过程多次而不必复制粘贴查询,如果您想更新查询,您只需要在一个地方更新它。

4)减少网络流量。如上所述,这对大多数人来说可能不是问题,但对于大型应用程序,通过切换到使用存储过程,可以显着减少通过网络传输的数据量。

+3

任何存储过程必须首先进行分析,确定执行计划等才能被缓存。任何参数化查询都经历了相同的过程,因此与存储过程真的具有相同的性能优势 – 2011-12-19 10:00:54

+0

多数民众赞成在有趣的感谢,我一直认为这个过程实际上是优化存储过程。 – Purplegoldfish 2011-12-19 10:17:01

+1

但是执行计划不会为存储过程而无限期地存储,并且每次都会产生临时查询?事情可能已经发生了变化,但这是我以前相信的。这可能意味着使用存储的特效可获得巨大的性能提升虽然如果我没有正确记住,这取决于你在存储过程中做了什么,如果它很复杂,执行计划可能在每次调用时都会重新生成。任何意见? – infocyde 2012-12-05 23:55:28

0

与标准SQL语句不同,存储过程由数据库服务器编译和优化。此优化涉及使用有关存储过程在执行时所需的特定数据库结构的信息。存储执行信息(执行计划)的这个过程是极大的节省时间,特别是如果存储过程被多次调用。

速度也因存储过程完全在数据库服务器上运行这一事实而得到改进 - 不需要通过网络传递大量SQL代码。对于一个简单的SELECT语句,可能不会有很大的不同,但在我们进行一系列的循环和计算的情况下,它可以有显著的效果。

+4

这不完全正确;正确的参数化查询就像编译和存储在​​SQL Server的计划缓存中一样 - 在执行速度/性能方面实际上没有太多(如果有的话)差异。 – 2011-12-19 09:50:11

3

你的语句存储过程是比SQL查询更快避免只是部分正确。解释:大多数这些答案已经解释了使用存储过程生成并缓存查询计划。因此,如果再次调用存储过程,SQL引擎将首先搜索其查询计划列表,如果找到匹配项,它将使用优化计划。

传递正常查询不允许使用此优势,因为SQL引擎不知道该期待什么,因此无法为您的查询找到匹配项。它从头开始创建一个计划,然后呈现结果。

好消息:您可以使用参数化查询(SQL中的一项新功能)为查询启用计划缓存。这使您能够为您的查询生成计划,并且在您的情况下可以非常有效,因为您从代码传递的大多数查询都保持不变,除了Where子句中的大部分变量。还有一个设置可以强制所有查询的参数化。搜索这个主题的MSDN,应该帮助你决定什么是最好的。

然而,此说,存储过程仍然与DB从您的应用程序进行交互,因为它提供了一个额外的安全层的好方法。

希望这有帮助!

0
  1. 存储过程有时运行得快一点,因为或使用RPC调用时可能
  2. SP运行对于必须重新编译的查询速度更快 - 为前。 - 使用临时表的作品在中间
3

另一个问题是在什么地方看,比较web服务器和这个 -

EXEC的someproc @ VAR1 =“嗒嗒”数据库服务器之间的网络流量, @ VAR2 = '嗒嗒',@ VAR3 = '嗒嗒'

为了这个 -

选择场,场2,字段3,字段4,字段5,字段6 .... field30 上table2.field12 =表1表1加盟.field12 where blah blah blah 和table1.field3 = @ var1的和table2.field44 = @ var2的和(table1.field1为空或table1.field1 = @ VAR3 .......

查看不同?对我们99%的人来说,这可能并不重要,但是对于你们中的一些人来说,编写高性能的应用程序可能会这样,尽管可能有一些缓存或其他处理方式。

我想有很多人谁声称有即席查询和存储过程没有什么区别,一般使用表作为对象存储为他们所使用的任何ORM,这是好的。仍然有很多大量的数据驱动的企业应用程序,无论是正确的还是错误的,都有超过1000行的存储过程。你最终可能会在他们身上工作。此外,对于那些你们谁可能不得不在一段时间每一次生产的变化和需要绕过正规程序是很多比生产编译代码更容易做到这一点在数据库中。改变proc ...完成。牛仔,可怕,邪恶,发生。是的,我知道在你的许多想法中这样做是不可饶恕的罪行,剪切斜坡的迹象......但它发生了。只是要考虑一下。

我知道最新的工具通常使用存储的特效痛苦在后面,如果你期望得到很好地为您生成所有的实体做出,但存储的特效依然有自己的位置的时候。

+1

假设您的网格一次显示20条记录,但查询返回20,000条匹配记录。使用实体框架,您可以在代码中进行分页,以便将20,000条记录中的数据剪切为20条记录,并将其传送至浏览器。但是20,000个记录仍然从数据库服务器发送到Web服务器。通过存储过程,您可以在proc中处理分页逻辑,因此20条记录从数据库服务器发送到Web服务器,然后发送到客户端。数据库服务器和Web服务器之间的流量较少。还有别的想法。 – infocyde 2015-02-03 23:07:38

+0

[冗余],已删除。 – infocyde 2015-02-03 23:08:20

+0

对于Entity Framework来说,这种情况并不那么正确,它似乎只处理了20个需要的记录,而没有数据库服务器吮吸20,000个记录,就像我们的例子中那样。尽管Web服务器和数据库服务器之间的数据流量仍然是一个问题。存储的特效减少了。 – infocyde 2018-01-24 23:16:13

相关问题