哪个更好:即席查询或者存储过程?
假设由于某种原因无法使用LINQ,将查询放在存储过程中是更好的做法,还是对数据库执行临时查询(例如,为论证而使用SQL Server)是否一样好?
解决方案
回答
存储过程很棒,因为无需重新编译就可以更改它们。我会尝试尽可能多地使用它们。
我仅将临时查询用于根据用户输入动态生成的查询。
回答
我从另一个帖子中得到的答案是:
存储过程更具可维护性,因为:
- 每当我们想更改一些SQL时,都不必重新编译C#应用程序
- 我们最终将重用SQL代码。
尝试构建可维护的应用程序时,代码重复是最糟糕的事情!
当我们发现需要在多个地方纠正的逻辑错误时,会发生什么情况?我们更容易忘记更改复制和粘贴代码的最后一个位置。
我认为,性能和安全性方面的收益是额外的优势。我们仍然可以编写不安全/效率低下的SQL存储过程。
Easier to port to another DB - no procs to port
用脚本编写所有存储过程以在另一个数据库中创建并不是很困难。实际上,这比导出表更容易,因为不需要担心主键/外键。
回答
取决于目标是什么。例如,如果要检索项目列表,并且该列表在应用程序的整个运行过程中发生一次,那么使用存储过程可能不值得。另一方面,重复执行并且花费(相对)较长时间执行的查询是数据库存储的极佳选择,因为性能会更好。
如果应用程序几乎完全存在于数据库中,那么存储过程就不费吹灰之力了。如果我们正在编写一个桌面应用程序,而该数据库仅对数据库具有切向重要性,则临时查询可能是一个更好的选择,因为它将所有代码都放在一个位置。
@Terrapin:我认为我们断言无需重新编译应用程序即可进行修改这一事实使存储过程成为一个更好的选择,这是毫无用处的。在临时查询中可能有选择存储过程的原因,但是在没有其他任何令人信服的情况下,编译问题似乎是懒惰而不是真正的原因。
回答
这两个存储过程都具有说服力,它们都位于中央存储库中,但是(可能)难以迁移,并且临时查询与代码一样容易调试,但是在代码中也很难找到它们。
关于存储过程更高效的争论不再成立。
连结文字
为存储过程与动态查询做一个Google会以任何方式显示体面的参数,并且可能最适合我们做出自己的决定...
回答
由于其他人提到的原因而对Procs进行处理,并且使用事件探查器或者proc的一部分对proc进行调优也更加容易。这样,我们不必告诉某人运行他的应用程序来查找发送到SQL Server的内容。
如果我们确实使用临时查询,请确保已对其进行了参数化
回答
参数化的SQL或者SPROC ...从性能的角度来看都没关系...我们可以查询优化其中之一。
对我来说,SPROC的最后一个好处是我可以通过仅授予我的登录权限来执行sprocs来消除很多SQL权限管理...如果我们使用参数化SQL,则带有连接字符串的登录名将具有更多的权限(写ANY例如,它们也可以访问其中一个表的一种select语句)。
我仍然更喜欢参数化SQL ...
回答
以我主要编写WinForms客户端/服务器应用程序的经验,这些是我得出的简单结论:
使用存储过程:
- 对于任何复杂的数据工作。如果要真正执行需要游标或者临时表的操作,则通常在SQL Server中最快。
- 当我们需要锁定对数据的访问时。如果我们不向用户(或者角色或者其他角色)授予表访问权限,则可以确保与数据交互的唯一方法是通过创建的SP。
使用即席查询:
- 对于CRUD,当我们不需要限制数据访问(或者以其他方式进行限制)时。
- 对于简单的搜索。为一堆搜索条件创建SP既麻烦又难以维护。如果我们可以生成合理快速的搜索查询,请使用它。
在我的大多数应用程序中,我同时使用了SP和临时sql,尽管我发现越来越少使用SP,因为它们最终像C#一样是代码,因此版本控制,测试和维护更加困难。我建议我们使用临时SQL,除非我们找到特定原因不这样做。
回答
这里要考虑一些事情:到底谁需要存储过程?
显然,这是我们自己的需求和偏好的问题,但是在面向公众的环境中使用即席查询时要考虑的一个非常重要的事情是安全性。始终对它们进行参数设置,并注意诸如SQL注入攻击之类的典型漏洞。
回答
存储过程表示一种软件合同,其中包含对数据库采取的操作。可以更改过程中的代码,甚至可以更改数据库本身的模式,而不会影响已编译的已部署代码,因此过程的输入和输出保持不变。
通过在应用程序中嵌入查询,我们可以将自己紧密地耦合到数据模型。
出于同样的原因,对数据库中的每个表简单地创建只是CRUD查询的存储过程也是一种不好的做法,因为这仍然是紧密耦合的。该程序应该是笨重的,粗粒度的操作。
从安全角度来看,优良作法是禁止从应用程序中使用db_datareader和db_datawriter,而仅允许访问存储过程。
回答
存储过程绝对是必经之路...它们经过编译,事先有执行计划,我们可以对它们进行权限管理。
我不了解存储过程中的整个源代码管理问题。如果只有一点点的纪律,我们绝对可以控制它们。
始终以.sql文件开头,该文件是存储过程的源。编写代码后,将其放入版本控制中。下次我们要编辑存储过程时,请从源代码管理而不是数据库中获取它。如果我们遵循此步骤,则将拥有与代码一样好的源代码控制。
我想在这里引用Oracle的Tom Kyte ...这是他在哪里编写代码的规则...虽然有点无关,但是我想知道。
- 从PL / SQL中的存储过程开始...
- 如果我们认为使用PL / SQL中的存储过程无法完成某些事情,请使用Java存储过程。
- 如果我们认为使用Java存储过程无法完成某些任务,请考虑使用Pro * c。
- 如果我们认为使用Pro * C无法实现某些目标,则可能需要重新考虑需要完成的工作。
回答
如果我们将SQL编写为代码,则已经准备好应付将来的麻烦了,应该尽可能使用存储过程。编写SPROC的时间与用代码编写SPROC的时间相同。
考虑一个在中等负载下运行良好的查询,但是一旦进入全职生产,我们最差的优化查询就会影响系统并将其带入爬网。在大多数SQL Server中,我们不是唯一使用它的应用程序/服务。现在,应用程序使一堆生气的人到了我们家。
如果我们在SPROC中有查询,则还允许友好的DBA进行管理和优化,而无需重新编译或者破坏应用程序。请记住,DBA是该领域的专家,他们知道该做什么和不该做什么。利用他们的更多知识是有道理的!
编辑:有人说重新编译是一个懒惰的借口!是的,让我们看看我们必须重新编译并将应用程序部署到1000个台式机时的感觉有多懒,这都是因为DBA告诉我们即席查询占用了太多服务器时间!
回答
我的经验是90%的查询和/或者存储过程都不应该(至少用手)编写。
数据访问应该以某种方式自动生成。我们可以决定是要在编译时静态生成过程还是在运行时动态生成过程,但是当我们想向表中添加列(对象的属性)时,我们应该只修改一个文件。
回答
对于使用临时查询,我还没有找到任何令人信服的论点。特别是那些与C#/ Java / PHP代码混合在一起的代码。
回答
someone said that recompile is a lazy excuse! yeah lets see how lazy you feel when you have to recompile and deploy your app to 1000's of desktops, all because the DBA has told you that your ad-hoc Query is eating up too much Server time!
如果让1000个台式机直接连接到数据库,这是一种好的系统体系结构吗?
回答
除了SQL Server,我只能说其他任何东西,但是性能参数在那里不是很有效,除非我们使用的是6.5或者更早版本。 SQL Server已经缓存了临时执行计划大约十年了。
回答
is it good system architecture if you let connect 1000 desktops directly to database?
不,显然不是,这可能是一个糟糕的例子,但我想我想说的很清楚,DBA照顾数据库基础架构是他们的专长,将SQL塞入代码中为他们和他们的专长上锁了。
回答
在我们的应用程序中,有一层代码提供查询的内容(有时是对存储过程的调用)。这使我们能够:
- 轻松地将所有查询置于版本控制之下
- 对不同数据库服务器的每个查询进行所需的更改
- 通过我们的代码消除了相同查询代码的重复
访问控制是在中间层而不是数据库中实现的,因此我们不需要那里的存储过程。从某种意义上讲,这是临时查询和存储过程之间的中间道路。
回答
我更喜欢将所有数据访问逻辑保留在程序代码中,其中数据访问层执行直接的SQL查询。另一方面,我将数据管理逻辑以触发器,存储过程,自定义函数之类的形式放入数据库中。我认为值得数据库验证的一个例子是数据生成,假设我们的客户有一个名字和一个姓氏。现在,用户界面需要一个DisplayName,它是从一些平凡的逻辑派生而来的。对于这一代,我创建了一个存储过程,每当行(或者其他源数据)被更新时,触发器便会执行该存储过程。
似乎存在一些常见的误解,即数据访问层是数据库,而有关数据和数据访问的所有内容都"因为"而进入了数据库。这是完全错误的,但是我看到很多设计都源于这个想法。不过,这也许是局部现象。
在看到了很多设计不良的SP之后,我可能只是关闭了SP的想法。例如,我参与的一个项目为每个表及其遇到的每个可能的查询使用了一组CRUD存储过程。这样,他们只是添加了另一个完全没有意义的层。甚至想到这样的事情都是痛苦的。
回答
这些天,我几乎从未使用过存储过程。我仅将它们用于无法通过代码轻松完成的复杂SQL查询。
主要原因之一是因为存储过程在OR映射器中无法正常工作。
这些天,我认为我们需要一个很好的理由来编写不使用某种OR映射器的业务应用程序/信息系统。
回答
我认为这是必须维护数据库的人员与开发用户界面的人员之间的基本冲突。
作为数据人员,我不会考虑使用通过即席查询访问的数据库,因为它们很难有效地进行调整或者管理。我怎么知道更改架构会有什么影响?此外,出于安全原因,我不认为应该授予用户直接访问数据库表的权限(我不仅指SQL注入攻击,还因为它是基本的内部控件,不允许直接权限,并且要求所有用户仅使用为该应用程序设计的proc。这是为了防止可能的欺诈行为。任何允许直接插入,更新或者删除表权限的财务系统都存在巨大的欺诈风险(这是一件坏事。)
数据库不是面向对象的,而从面向对象的角度看似乎不错的代码从数据库的角度来看可能非常糟糕。
我们的开发人员告诉我们,我们对所有的数据库访问都是通过proc感到很高兴,因为它可以更快地修复以数据为中心的bug,然后仅在生产环境中运行proc,而不是创建代码的新分支并重新编译和重新加载到生产中。我们要求所有过程都在Subversion中,因此源代码控制根本不是问题。如果不在Subversion中,它将被dbas定期删除,因此不存在使用Source Control的阻力。
回答
存储过程作为代码块工作,因此代替即席查询,它可以快速工作。
另一件事是存储过程给出最好的一部分的重新编译选项
SQL只是将它用于存储过程,而在addhoc查询中却没有这样。
查询和存储过程中的某些结果不同,这是我个人的经验。
使用强制转换和隐藏功能进行检查。
必须对大型项目使用存储过程以提高性能。
我的项目中有420个程序,对我来说很好。我在这个项目上工作了三年。
因此,仅对任何交易使用过程。
回答
sproc性能参数是针对3个顶级RDBM使用查询计划缓存的,并且已经存在了一段时间。它被记录下来了……还是1995年仍然是?
但是,在应用程序中嵌入SQL是一个糟糕的设计,对于许多人来说,代码维护似乎也是一个缺少的概念。
如果应用程序可以从头开始使用ORM(新建应用程序之间相差无几!),那么它是一个不错的选择,因为类模型可以驱动数据库模型并节省大量时间。
如果没有ORM框架,我们将采用混合方法创建SQL资源XML文件来根据需要查找SQL字符串(然后由资源框架对其进行缓存)。如果SQL需要任何小的操作,如果需要主要的SQL字符串操作,则可以在代码中完成。
这种混合方法使开发人员易于管理(也许是少数,因为我的团队足够聪明来阅读查询计划),并且部署是SVN的简单结帐。而且,它仅交换SQL资源文件就使切换RDBM更加容易(当然不如ORM工具那么简单,但是连接到旧系统或者不受支持的数据库即可)