【发布时间】:2011-12-19 09:42:10
【问题描述】:
事实上,如果我从我的应用程序调用存储过程,我需要连接到我的数据库。
那么,为什么调用“存储过程”应该比“传递 SQL 查询”字符串更快?
【问题讨论】:
-
这些天来,存储过程确实不再有太多的速度优势了。正确参数化的查询将与存储过程一样有效。仅凭这一点并不是使用存储过程的好理由
标签: sql sql-server stored-procedures
事实上,如果我从我的应用程序调用存储过程,我需要连接到我的数据库。
那么,为什么调用“存储过程”应该比“传递 SQL 查询”字符串更快?
【问题讨论】:
标签: sql sql-server stored-procedures
SQL Server 基本上通过这些步骤来执行任何查询(存储过程调用或即席 SQL 语句):
1) 语法检查查询
2) 如果没问题 - 它检查计划缓存以查看它是否已经有该查询的执行计划
3) 如果有执行计划 - 该计划被(重新)使用并执行查询
4)如果还没有计划,则确定执行计划
5) 该计划被存储到计划缓存中以供以后重用
6) 查询被执行
重点是:即席 SQL 和存储过程在处理上没有什么不同。
如果 ad-hoc SQL 查询正确使用参数 - 无论如何它应该使用参数,以防止 SQL 注入攻击 - 它的性能特征没有什么不同,而且绝对不会比执行存储过程差。
存储过程还有其他好处(例如,无需授予用户直接表访问权限),但就性能而言,使用适当参数化的即席 SQL 查询与使用存储过程一样高效程序。
更新:在非参数化查询上使用存储过程更好,主要有两个原因:
由于每个非参数化查询都是对 SQL Server 的新的、不同的查询,因此对于每个查询,它都必须经过确定执行计划的所有步骤(因此浪费时间- 并且还浪费计划缓存空间,因为将执行计划存储到计划缓存中最终并没有真正的帮助,因为该特定查询可能不会再次执行)
非参数化查询存在 SQL 注入攻击的风险,应不惜一切代价避免
【讨论】:
因为每次将查询字符串传递给 SQL Server 时,都必须编译代码等,存储过程已经编译并准备好在服务器上运行。
虽然这通常影响很小,但您通过网络发送的数据也较少。
编辑: 作为旁注,存储过程还有其他好处。
1) 安全性 - 由于实际查询存储在服务器上,因此您不会通过网络传输它,这意味着任何拦截您的网络流量的人都无法深入了解您的表结构。设计良好的 SP 也可以防止注入攻击。
2) 代码分离,将数据库代码保存在数据库中,将应用程序代码保存在应用程序中,几乎没有交叉,我发现这使得错误修复变得更好。
3) 可维护性和代码重用,您可以多次重用一个过程,而无需复制粘贴查询,如果您希望更新查询,您只需在一处更新即可。
4) 减少网络流量。如上所述,这对大多数人来说可能不是问题,但对于大型应用程序,您可以通过切换到使用存储过程来显着减少通过网络传输的数据量。
【讨论】:
您关于存储过程比 SQL 查询快的说法只是部分正确。解释一下:这些答案中的大多数已经解释了使用存储过程会生成和缓存查询计划。因此,如果您再次调用存储过程,SQL 引擎首先搜索其查询计划列表,如果找到匹配项,则使用优化计划。
传递一个普通的查询并没有这个优势,因为 SQL 引擎不知道会发生什么,因此它无法为您的查询找到匹配项。它从头开始制定计划,然后呈现您的结果。
好消息:您可以使用参数化查询(SQL 中的一项新功能)为您的查询启用计划缓存。这使您能够为查询生成计划,并且在您的情况下非常有效,因为您从代码传递的大多数查询保持不变,除了 Where 子句中的变量。还有一个设置,您可以在其中强制对所有查询进行参数化。在 MSDN 中搜索此主题,应该可以帮助您决定什么是最好的。
不过,也就是说,存储过程仍然是从应用程序与数据库交互的好方法,因为它提供了额外的安全层。
希望这对您有所帮助!
【讨论】:
这篇文章解释得很好: https://codingsight.com/dynamic-sql-vs-stored-procedure/
根据我的经验,存储过程肯定更快,因为减少了网络流量(不必发送整个查询)以及过程和查询计划的缓存。
我在一个填充了用户登录数据的表上运行了类似于以下的代码。
"select top 1 * from Logons where ComputerName=@ComputerName order by LogonTime desc"
对 7000 个计算机名称运行查询耗时 2 小时。
当我将查询放入存储过程中时,大约需要一分钟才能在 7000 个计算机名称上运行。
我敢肯定,如果您只运行一次查询,则每次查询花费 1 秒与 10 毫秒对人类没有太大影响。但是,如果您需要运行一千次查询,则相差 1000 秒(大约 16 分钟)与 10 秒。
【讨论】:
另外一个被忽略的问题,对比一下这个的web服务器和数据库服务器的网络流量-
执行 someproc @var1='blah', @var2='blah', @var3='blah'
到这里-
选择字段1、字段2、字段3、字段4、字段5、字段6....字段30 在 table2.field12 = table1.field12 上加入 table1 在哪里等等等等 and table1.field3 = @var1 and table2.field44 = @var2 and (table1.field1 is null or table1.field1 = @var3.......
看到区别了吗?对于我们 99% 的人来说,这可能无关紧要,但对于一些编写高性能应用程序的人来说,这可能是重要的,尽管可能有一些缓存或其他方法来处理这个问题。
我认为很多声称即席查询和存储过程之间没有区别的人通常将表用作他们使用的任何 ORM 的对象存储,这很好。仍然有很多大数据驱动的企业应用程序,无论对错,都有超过 1000 行的存储过程。你最终可能会在他们身上工作。此外,对于那些可能不得不每隔一段时间在生产环境中进行更改并需要绕过正式流程的人来说,在数据库中执行此操作比在生产编译代码中更容易很多。更改过程...完成。牛仔,可怕,邪恶,发生了。是的,我知道这样做在你的许多人心目中是不可原谅的罪过,是剪断的迹象……但它确实发生了。也是需要考虑的事情。
我知道,如果您希望所有实体都能为您很好地生成,那么最新的工具通常会让使用存储过程变得很麻烦,但有时存储过程仍然占有一席之地。
【讨论】:
存储过程被编译和缓存。但是 SQL 语句将与现有的执行计划进行比较,如果存在匹配则使用,因此在某种程度上抵消了任何优势。
多次执行后的实际性能差异是多少?
【讨论】:
sql = “Select * from Employees where Lastname = ‘” & ddl.selecteditem.text & “‘”,而不是sql = “Select * from Employees where Lastname =@LastName”
与标准 SQL 语句不同,存储过程由数据库服务器编译和优化。此优化涉及使用有关存储过程执行时所需的特定数据库结构的信息。这种存储执行信息(执行计划)的过程非常节省时间,尤其是在存储过程被多次调用的情况下。
存储过程完全在数据库服务器上运行也提高了速度 - 无需通过网络传递大量 SQL 代码。对于一个简单的 SELECT 语句,这可能不会产生太大的影响,但在我们执行一系列循环和计算的情况下,它可能会产生显着的影响。
【讨论】:
【讨论】: