哪个更好:即席查询或存储过程?

时间:2008-08-22 17:10:30

标签: sql stored-procedures

假设您出于某种原因无法使用LINQ,将查询放在存储过程中是一种更好的做法,还是对数据库执行 ad hoc 查询是一种很好的做法(说,SQL Server是为了参数的缘故)?

22 个答案:

答案 0 :(得分:92)

根据我编写WinForms客户端/服务器应用程序的经验,这些是我得出的简单结论:

使用存储过程:

  1. 对于任何复杂的数据工作。如果您要做一些真正需要游标或临时表的事情,那么在SQL Server中执行它通常是最快的。
  2. 当您需要锁定对数据的访问权限时。如果您不向用户(或角色或其他)提供表访问权限,则可以确保与数据交互的唯一方法是通过您创建的SP。
  3. 使用即席查询:

    1. 对于CRUD,当您不需要限制数据访问时(或以其他方式这样做)。
    2. 简单搜索。为一堆搜索标准创建SP是一件痛苦的事情并且难以维护。如果您能够生成相当快速的搜索查询,请使用它。
    3. 在我的大多数应用程序中,我都使用了SP和ad-hoc sql,虽然我发现我使用的SP越来越少,因为它们最终成为像C#一样的代码,只是更难以进行版本控制,测试和保持。我建议使用ad-hoc sql,除非你能找到一个特定的理由不这样做。

答案 1 :(得分:27)

我不能说除SQL Server之外的其他任何内容,但性能参数在那里非常有效,除非您使用6.5或更早版本。 SQL Server已经缓存了大约十年的临时执行计划。

答案 2 :(得分:13)

存储过程表示封装对数据库采取的操作的软件合同。程序中的代码,甚至数据库本身的模式都可以在不影响已编译的已部署代码的情况下进行更改,只是因此过程的输入和输出保持不变。

通过在您的应用程序中嵌入查询,您可以将自己与数据模型紧密结合。

出于同样的原因,简单地创建仅针对数据库中每个表的CRUD查询的存储过程也是不太好的做法,因为这仍然是紧密耦合。相反,程序应该是庞大的粗粒度操作。

从安全角度来看,最好不要从应用程序中禁用db_datareader和db_datawriter,只允许访问存储过程。

答案 3 :(得分:12)

我认为这是必须维护数据库的人与开发用户界面的人之间的基本冲突。

作为数据人,我不会考虑使用通过adhoc查询访问的数据库,因为它们很难有效地调整或管理。我如何知道对架构的更改会产生什么影响?此外,出于安全原因,我认为不应该授予用户直接访问数据库表的权利(我不仅仅意味着SQL注入攻击,而且因为它是一个基本的内部控制,不允许直接权限并要求所有用户只使用为应用程序设计的过程。这是为了防止可能的欺诈。任何允许直接插入,更新或删除表权限的金融系统都存在欺诈的巨大风险。这是一件坏事。)。

数据库不是面向对象的,从面向对象的角度来看似乎很好的代码从数据库的角度来看可能非常糟糕。

我们的开发人员告诉我们他们很高兴我们所有的数据库访问都是通过procs,因为它可以更快地修复以数据为中心的bug,然后只需在生产环境中运行proc而不是创建一个新的代码分支并重新编译并重新加载到生产中。我们要求所有的proc都处于颠覆状态,所以源控制根本不是问题。如果它不在Subversion中,它会定期被dbas删除,因此没有阻止使用Source Control。

答案 4 :(得分:6)

存储过程绝对是要走的路......它们是经过编译的,具有执行计划,您可以对它们进行权限管理。

我不了解存储过程的整个源代码控制问题。如果只是你有点自律,你绝对可以控制它们。

始终以作为存储过程源的.sql文件开头。编写代码后,将其置于版本控制中。下次要编辑存储过程时,从源控件获取它而不是数据库。如果你遵循这个,你将拥有与你的代码一样好的源代码控制。

我想在这里引用Oracle的Tom Kyte ......这是他编写代码的地方的规则......虽然有点无关但我很想知道。

  1. 从PL / SQL中的存储过程开始......
  2. 如果您认为使用PL / SQL中的存储过程无法完成某些操作,请使用Java存储过程。
  3. 如果您认为使用Java存储过程无法完成某些操作,请考虑使用Pro * c。
  4. 如果您认为使用Pro * C无法实现某些目标,您可能需要重新考虑完成所需的工作。

答案 5 :(得分:4)

在我们的应用程序中,有一层代码提供查询内容(有时是对存储过程的调用)。这允许我们:

  • 轻松拥有版本控制下的所有查询
  • 使不同数据库服务器的每个查询都需要进行更改
  • 通过我们的代码
  • 消除了相同查询代码的重复

访问控制在中间层实现,而不是在数据库中实现,因此我们不需要存储过程。这在某些方面是即席查询和存储过程之间的中间道路。

答案 6 :(得分:3)

我的回答from a different帖子: 存储过程 MORE 可维护,因为:

  • 无论何时想要更改某些SQL
  • ,都不必重新编译C#应用程序
  • 您最终会重用SQL代码。

代码重复是您在尝试构建可维护应用程序时可以执行的最差事情!

当您发现需要在多个位置更正的逻辑错误时会发生什么?你更容易忘记改变你复制的最后一个位置&粘贴你的代码。

在我看来,表现&安全收益是一个额外的加分。 您仍然可以编写不安全/效率低下的SQL存储过程。

  

更容易移植到另一个数据库 - 没有移植到端口

在另一个数据库中编写用于创建的所有存储过程并不是很困难。事实上 - 它比导出表格更容易,因为没有主要/外键需要担心。

答案 7 :(得分:3)

两者都有令人信服的论据 - 存储过程都位于中央存储库中,但是(可能)难以迁移,并且即席查询更容易调试,因为它们与您的代码一样,但它们也可能更难在代码中找到。

存储过程更有效的论点不再存在。 link text

对存储过程和动态查询执行谷歌会以任何方式显示不错的论据,可能最适合您做出自己的决定......

答案 8 :(得分:3)

如果您将SQL编写成代码,那么您应该尽可能地使用存储过程,这样您就已经为未来的头痛做好了准备。编写SPROC需要大约相同的时间,就像在代码中编写SPROC一样。

考虑一个在中等负载下运行良好的查询,但一旦进入全时生产,您的严重优化查询会破坏系统并使其爬行。在大多数SQL服务器中,您不是唯一使用它的应用程序/服务。你的申请现在已经把一群愤怒的人带到你家门口。

如果您在SPROC中有疑问,您还可以让友好的DBA通过重新编译或破坏您的应用来管理和优化。记住DBA是这个领域的专家,他们知道该做什么而不做。利用他们的更多知识是有意义的!

编辑:有人说重新编译是一个懒惰的借口!是的,让我们看看当你不得不重新编译和部署你的应用程序到1000个桌面时你感觉有多懒,这都是因为DBA告诉你你的ad-hoc查询占用了太多的服务器时间!

答案 9 :(得分:2)

有些事情需要考虑:Who Needs Stored Procedures, Anyways?

显然,这取决于您自己的需求和偏好,但在面向公众的环境中使用即席查询时要考虑的一个非常重要的事情是安全性。始终对它们进行参数化,并注​​意SQL-injection attacks等典型漏洞。

答案 10 :(得分:2)

  有人说重新编译是一个懒惰的借口!是的,让我们看看当你不得不重新编译和部署你的应用程序到1000个桌面时你感觉有多懒,这都是因为DBA告诉你你的ad-hoc查询占用了太多的服务器时间!

如果你让1000台桌面直接连接到数据库,它是不是很好的系统架构?

答案 11 :(得分:1)

sproc性能论证没有实际意义 - 3个顶级RDBM使用查询计划缓存并且已经有一段时间了。它已被记录......或者仍然是1995年?

然而,在您的应用程序中嵌入SQL也是一个糟糕的设计 - 对于许多人来说,代码维护似乎是一个缺失的概念。

如果一个应用程序可以从头开始使用ORM(绿地应用程序很少而且很少!),这是一个很好的选择,因为您的类模型驱动您的数据库模型 - 并节省了大量时间。

如果ORM框架不可用,我们采用混合方法创建SQL资源XML文件,以便在需要时查找SQL字符串(然后由资源框架缓存它们)。如果SQL需要在代码中完成任何微小操作 - 如果需要进行主要的SQL字符串操作,我们会重新考虑这种方法。

这种混合方法有助于开发人员轻松管理(可能我们是少数,因为我的团队足够聪明,可以阅读查询计划),部署是SVN的简单结账。此外,它使得切换RDBM变得更容易 - 只需换出SQL资源文件(当然不像ORM工具那么简单,但是连接到遗留系统或不支持的数据库这样做)

答案 12 :(得分:1)

存储过程非常棒,因为无需重新编译即可更改它们。我会尝试尽可能多地使用它们。

我只对基于用户输入动态生成的查询使用ad-hoc。

答案 13 :(得分:1)

我没有找到使用即席查询的任何令人信服的论据。特别是与您的C#/ Java / PHP代码混淆的那些。

答案 14 :(得分:1)

参数化SQL或SPROC ......从性能角度来看无关紧要......您可以查询优化任何一个。

对我来说,SPROC的最后一个好处是我可以通过仅授予执行sprocs的登录权限来消除大量的SQL权限管理...如果使用Parametized SQL,那么使用您的连接字符串的登录具有更多权限(例如,在他们有权访问的一个表上写任何类型的select语句)。

我仍然更喜欢Parametized SQL ...

答案 15 :(得分:1)

由于其他人提到的原因而进行处理,并且使用探查器或部分proc更容易调整proc。这样您就不必告诉某人运行他的应用程序以找出发送到SQL服务器的内容

如果您确实使用临时查询,请确保它们已参数化

答案 16 :(得分:0)

我的经验是,根本不应该写入90%的查询和/或存储过程(至少是手工编写)。

应以某种方式自动生成数据访问。您可以决定是在编译时静态生成过程还是在运行时动态生成过程,但是当您想要向表中添加列(对象的属性)时,您应该只修改一个文件。

答案 17 :(得分:0)

我更喜欢在程序代码中保留所有数据 access 逻辑,其中数据访问层执行直接的SQL查询。另一方面,数据管理逻辑我以触发器,存储过程,自定义函数和诸如此类的形式放入数据库。我认为值得数据库处理的一个例子是数据生成 - 假设我们的客户有FirstName和LastName。现在,用户界面需要一个DisplayName,它来自一些非平凡的逻辑。对于这一代,我创建了一个存储过程,然后在更新行(或其他源数据)时由触发器执行。

似乎有一种常见的误解,即数据访问层是数据库,关于数据和数据访问的一切都在那里“只是因为”。这是完全错误的,但我看到很多设计源于这个想法。也许这是一个当地的现象。

在看到如此多设计糟糕的SP之后,我可能只是关闭了SP的想法。例如,我参与的一个项目为每个表和他们遇到的每个可能的查询使用了一组CRUD存储过程。在这样做时,他们只是添加了另一个完全无意义的层。想想这些事情是痛苦的。

答案 18 :(得分:0)

这些天我几乎不使用存储过程。我只将它们用于复杂的SQL查询,这些查询无法在代码中轻松完成。

其中一个主要原因是因为存储过程与OR映射器不兼容。

这些天我认为你需要一个很好的理由来编写一个不使用某种OR映射器的业务应用程序/信息系统。

答案 19 :(得分:0)

存储过程作为代码块工作,因此代替adhoc查询它可以快速工作。 另一件事是存储过程给出重新编译选项最好的部分 SQL只是在adhoc查询中使用它来存储过程。

查询和存储过程的某些结果是不同的,这是我的个人exp。 使用cast和covert函数进行检查。

必须使用大型项目​​的存储过程来提高性能。

我的项目中有420个程序,这对我来说很好。我在这个项目上工作了3年。

因此,只对任何交易使用程序。

答案 20 :(得分:0)

取决于您的目标。例如,如果要检索项目列表并在应用程序的整个运行期间发生一次,则可能不值得使用存储过程。另一方面,重复运行并执行(相对)长时间的查询是数据库存储的理想选择,因为性能会更好。

如果您的应用程序几乎完全位于数据库中,那么存储过程就很简单。如果您正在编写一个只对数据库有重要意义的桌面应用程序,那么即席查询可能是更好的选择,因为它keeps all of your code in one place

@Terrapin:我认为你断言你不需要重新编译应用程序来进行修改这一事实使得存储过程成为一个更好的选择是不可能的。可能有理由选择存储过程而非ad-hoc查询,但在没有任何其他令人信服的情况下,编译问题似乎是懒惰而不是真正的原因。

答案 21 :(得分:-1)

  

如果你是好的系统架构   让我们直接连接1000台桌面   数据库?

不,它显然不是,它可能是一个糟糕的例子,但我认为我试图提出的观点是明确的,你的DBA照顾你的数据库基础设施,这是他们的专业知识,填充SQL代码锁定他们的大门和他们的专长。