sql存储过程vs代码,哪一个更好?

时间:2015-02-12 06:03:36

标签: c# mysql sql-server asp.net-mvc database

我在MVC中创建了一个Web应用程序的体系结构。 Web应用程序将维护电子商务类型的数据。两种方法之间出现了一点混乱,

  1.   

    我是否应该在类文件(模型) 中保留所有计算/数据访问代码,这些代码将使用 EDM 来访问DATA。通过EDM中访问的数据将通过MODEL文件中可用的代码进行优化并由控制器访问。在这种方法中,我将仅创建少数模型,其余模型将由EDM创建,并且可以直接绑定到视图。

  2.   

    我是否应该在存储过程 中保留所有计算/数据访问代码,这些代码将使用 SQL查询来访问DATA。通过存储过程中的 SQL查询访问的数据将由MODEL文件中可用的代码直接使用,并由控制器访问。在这种方法中,我将创建许多模型,因为我将不得不设置STORED过程的参数。

  3. 这里出现了问题,

    • 哪种方法最适合客户,第一或第二?为什么?

    • 这两种方法之间是否存在性能差异? 怎么样?

    • 哪种方法会更快实施?

    • 哪种方法更安全?

    提前谢谢你。

8 个答案:

答案 0 :(得分:10)

哪个最适合客户?让我们最后回答。

性能:

简短的回答是它不会有性能差异。在过去的SQL版本中,查询引擎会优化存储过程,但不会优化临时查询。当前版本的SQL没有区别。 SQL存储每个执行计划,只要它可以(存储proc或不存储),并且如果可以的话将重用它。 专业提示 - 尽量不要让你的where子句太疯狂,SQL可以更容易地重用它。有时,编写一些简单的查询比编写一个大型的大型查询更好。但这是一个有很多因素的大问题!

更快的实施:

这很容易。在过去的12年里,我已经完成了这两种方法,毫无疑问,编写存储过程的工作量更大。它也可能导致许多错误,因为它是另一层保姆。如果客户让我避免存储过程,我会将报价减少10%。但许多客户坚持要我使用它们。

引导我们...... 更安全的:

存储过程更安全,这就是原因。使用存储过程,您只需将一个角色授予SQL登录 - 存储过程的执行权限。当然,你可以用它做很多伤害,但它仍然有限。使用特殊查询(如Entity框架),您必须直接授予对表的完全读写权限。

这种区别曾经对我很重要,在数十家公司的数十个项目之后购买,我真的不在乎这个细微差别了。如果您遭到黑客入侵并且他们可以直接访问您的SQL以及您的用户名和密码,那么此级别的权限差异就不是问题。

我的观点是,避免存储过程会同样快速,使您能够更快地编码,并且安全性不会明显降低。

答案 1 :(得分:2)

作为我工作的一部分,我从事编写SQL存储过程已有8年了。如果您在公司工作而不是一个人工作,那么如果可以选择在软件中实现该功能,则不要使用存储过程。

如果您要快速遍历数据库行,则存储过程对于提高速度非常有用,因为它可以节省传输时间和通过网络将数据从数据库传送到软件的成本;但是有一些真正可怕的缺点。

1)编码困难/昂贵。存储过程本身就是一种强大的语言。我将他们的困难和笨拙等同于编写复杂的REGEX查询。 100行存储过程的难度可能等同于编写500个字符的REGEX查询。您将非常努力地工作,以确保您高效/正确地执行查询;如果您要负责雇用某人来执行工作,那么这将是昂贵的,因为此人需要具备专业技能。

2)略有关联,但是请不要低估代码支持的难度。如果您希望能够将此代码移交给其他人,则应一开始就选择使用一种常见且众所周知的语言。 我最终支持了我在一家公司工作的第一年编写的同一软件,直到我离开公司的第八年。我晋升为董事职位,并拥有数十名员工。但是我不能,而且公司中没有其他人可以信任另一个人来接管我将近十年前编写的代码-这对我来说是一个非常糟糕的菜鸟错误。

如果可以使用其他方法很好地解决您的问题,请避免使用存储过程。不要害怕它们,但永远不要将它们放在攻击新问题的工具列表的顶部。

答案 2 :(得分:1)

哪种方法最适合客户,第一还是第二?以及为什么?

假设某些人必须维护代码,因为代码会随时间变化,因此应用程序代码肯定更易于维护。

这两种方法之间是否会有性能差异?怎么样?

这不仅与数据库服务器VS应用程序服务器的处理能力有关。数据库的可伸缩性如何? DB倾向于在垂直方向上很好地扩展($$$),但在水平方向上则没有那么好。如果设计正确,软件应用程序可能会非常强大并且可以很好地横向扩展。 这是一个“依赖”问题。我们倾向于认为每个项目都应该以数据库为中心,并且我们总是开始设计实体关系模型,好像每个问题都必须用关系数据库来解决一样,或者业务逻辑应该取决于信息的存储方式。没有。如果您遵循DDD和干净或六边形的体系结构,则您的业务层(域)应完全独立于持久性层(或任何基础结构层)。有一些技术可以允许使用不同的模型进行读写操作,因为当数据被非规范化并且必须被合并使用时,数据库对于一致性的写入非常有用,而对于读操作却不是那么好的。

因此,答案是,这取决于您的体系结构和方法。我认为数据库是用来存储信息的东西,而不是为围绕它的业务构建解决方案。

哪种方法会更快实施?

这取决于谁实施它。对于复杂的业务领域,我怀疑您是否可以在数据库中使用业务逻辑而不会碰壁。 此外,考虑到自动测试技术相对于App代码(C#,Java,Scala,Javascript等)更好,因此如果避免使用存储过程并在其中使用业务逻辑,则可能会开发出更快,更好的代码。应用层(它所属的位置)

哪种方法更安全?

再次,这取决于。您是否在网络中公开数据库?数据库只能由单个应用程序访问吗?用户如何访问数据?

我已经看到许多公司因为在数据库中保留了遗留代码而埋葬了数千美元。我见过一些公司,其中特定的ER设计是业务中新场景的主要限制,它们采用微性能,添加索引,视图,缓存等方式,只是因为为时已晚(或昂贵,他们认为)是为了修改结构,或者是因为他们认为没有一个ER模型可以满足业务所需的所有功能,在大多数情况下都是如此,这也是不围绕数据库构建业务应用程序的最佳理由。

我见过一些公司,其中数据库被用作集成平台,每个团队都在其中接触某些事物,没有删除任何东西,因为人们害怕影响其他人,由于缺乏版本控制策略,某人的更改会影响许多其他人。等

由于种种原因,我已经看到足够多的人从未想到将业务逻辑放入数据库中。数据库旨在存储和查询数据,并且仅应用于此目的。

答案 3 :(得分:1)

通常,我将使用您的开发框架(在本例中为ASP.Net)提供的工具和思维模型。这给您很多好处,尤其是在可维护性(任何使用ASP.Net的开发人员可以选择该应用程序),安全性(您从所有框架安全性功能中受益)以及发展速度(您几乎肯定不会遇到独特的问题)。

对于ASP.Net,最常见的数据访问模式是使用实体框架。 EF基于您将使用ORM功能进行数据库访问的前提。这有很多好处:

  • 您编写的代码更少-CRUD操作开箱即用,您 不必手动将应用程序变量映射到数据字段
  • 您的思维模型是在应用程序模型级别,而不是特定的 实施级别
  • 您可以创建单元测试,因此可以确定 您的应用程序会按照您希望的方式运行
  • 您可以自动使应用程序代码和数据库架构保持同步

还有一些缺点:

  • 性能问题可能很难找出
  • 对于高度数据密集型的操作,您可能会获得较差的性能

因此,我的建议是使用第一个选择,即使用Entity Framework,并且仅在您具有大量数据密集型操作(例如,跨多个表的许多记录的计算)时才使用存储过程。

我建议将存储过程作为默认设置的原因:

  • 他们很难进行单元测试
  • 通过源代码控制很难将其保留在结构化的构建/部署脚本中
  • 它们很难调试
  • 对于一个开发人员来说,同时具备ASP.Net和SQL技能并不罕见-它们是非常不同的技能。
  • 您发现自己编写了很多重复的CRUD程序

答案 4 :(得分:0)

虽然可以在procs上进行单元测试(通常使用DB的附加组件),但我还没有在proc上进行单元测试的地方工作。大多数DBA我都知道讨厌数据库的附加组件。这也提出了源控制的重点。虽然存在源代码控制的附加组件,但大多数人都不会这样做。所以源代码控制变得比正常"更加痛苦。码。它不错,但它通常也没有整合。

我认为ORM确实让编码人员更轻松地将sql从proc中带出并进入(希望)一个Web服务。使用Web服务获取数据的一个好处是远离数据库的抽象(现在可以为您的产品支持多个数据库)以及缓存不会发生太大变化的数据。这导致了DBA非常喜欢的巨大的性能提升和更可预测的数据库访问!

答案 5 :(得分:0)

如果您可以清除可能的SQL注入攻击中的数据,那么从长远来看,将代码中的模型作为类将最终变得更容易理解,测试和调试。 此外,它还回答了其他一些问题。如果您想更改数据库该怎么办,如果您的旧数据库由于某种原因完全死了该怎么办。

答案 6 :(得分:0)

我已经在栅栏两边呆了近20年了,恕我直言 该问题的唯一正确答案应该是“取决于”。

但是让我对每个子主题都进行详细介绍。

性能

在SQL Server的早期,使用存储的proc确实可以更快地执行查询,这是因为存储的proc预编译查询的方式。但是随后引入了.NET Framework,并且将参数化查询与ADO.NET结合使用,因为它比经典ADO更快(它们还改进了OLEDB / JDBC / ODBC等),因此获得了很多基础。 举例来说,去年,我与一个SQL Server DBA团队和一个Java开发人员团队就此特定主题举行了内部研讨会,我要求两个团队构建解决方案以生成满足某些业务需求的报告。最佳解决方案将奖励给团队,但没有赢家!因此,基本上,我在这里要说的是,如果您的逻辑(和物理)数据模型可以,那么使用存储的proc和参数化的查询之间应该没有什么区别。

实施时间

如果您的IT部门主要由经验丰富的应用程序开发人员组成,他们几乎没有SQL Server(或任何其他数据库)经验,那么一路尝试存储过程将是愚蠢的。或者,采用相同的逻辑:如果您只有几个初级Web开发人员,但是有许多经验丰富的DBA,为什么不充分利用它们呢?例如,当前在我们的商店中,我们选择主要使用存储的proc进行数据访问,因为用户界面已经相当成熟,并且业务需求没有随着时间变化:输入参数和所需结果集没有变化。但是,我们正在与外部数据源进行大量合作,因此需要经常对物理数据模型的某些部分进行重新建模,在这里,存储过程的使用使我们能够灵活地更改我们使用的表和字段,同时确保输出相同。 实施和维护过程的另一个重要部分是源代码控制和测试。源代码控制数据库和单元测试编写无需其他工具和插件的帮助,而这并不是真正有趣且耗时的。可以做到,但是要通过内置Git支持之类的东西来达到公平的竞争环境,您必须有预算为数据库平台购买必要的工具,并拥有进行这项工作的经验。您应该在这里考虑的另一件事是上市时间。假设您的老板希望您立即使新产品投入使用,并且他对维护成本不屑一顾。然后,我最初的想法是使用尽可能少的数据库编码进行原型设计和RAD。但是,请再次注意您和您的同事可用的技能。

安全

根据我的经验,是否选择存储的过程取决于您需要哪种授权模型以及(再次)您的专业知识是什么。存储的proc可以非常安全地使用,因为您可以在非常细粒度的级别上授予执行权限,而无需用户直接访问数据库表。 SQL注入的机会实际上为零,但是可以将相同的原理应用于适当的参数化查询。同样,请看一下您在数据库和/或Windows管理(或Azure / AWS / Google / ...)方面的知识和经验。最重要的是:检查指定的用户组并确定可能的攻击面。

总结

无论主题是涉及客户还是我提到的其他专业领域,我都无法为您提供建议,因为答案实际上取决于很多因素,例如资源,经验,预算,可维护性,灵活性和业务要求等。但是,我确实希望您能够做出明智的,明智的决定,并祝您在项目中取得成功并取得成功!

答案 7 :(得分:0)

哪种方法更安全?

安全质量不是由方法定义的,而是由

  • 开发人员的技能-大多数MVC框架都具有许多build-in安全增强功能,但这并不意味着它不能编写具有注入风险的SQL即席查询,并且可以在存储过程中进行连接在动态T-SQL语句中输入参数,并且注入风险代码再次在线;
  • 管理员/ devops /数据库-安全性取决于其他人-是所用软件的最新版本,已安装的安全补丁,是否已续订SSL证书(在我曾为过时的驱动程序工作的公司中,该应用程序将APP与使用数据库,迁移该应用程序以使用新的应用程序太困难了;后者使用的驱动程序是un-deprecated并且发布了新的驱动程序,但仍未完成迁移-关键是无法泄漏由您解决)
  • 业务需求-有时业务目标如此怪异,以至于您需要比应有的机会更多地公开数据或功能;

哪种方法会更快实施?

最终目标定义了该方法的速度:

  • 创建一个简单的应用程序-选择MVC-在每个MVC框架随附的数百个插件中使用所需的数量,并在几分钟内构建该应用程序;
  • 创建一个复杂的应用程序-好吧,如果MVC插件可以快速完成一些工作,例如授权,登录页面等。为什么不使用它们-如果不是那么通用,请自己编写代码;

性能会有差异吗?

这取决于各种因素,例如:

  • 如果计算简单-使用较小的数据子集,而不是不断修改数据和大量静态内容-可能不会看到性能差异;
  • 开发人员的技能-我已经看到存储过程将一行修改为在应用程序中循环调用数千次,而不是传递所有数据并进行批量修改;
  • 语句有多复杂-我也看到过ORM库也可以将某些模型交互转换为无效的SQL语句;
  • 如果您需要执行聚合和大量过滤操作,则编写SQL然后使用模型可以更快(特别是对于大量数据);

哪种方法最适合客户?

大多数客户不具备技术知识。因此,客户需要快速(便宜)的方法-MVC。我发现很难说服客户投入更多的时间(花更多的钱),以准备将来处理重负载或更多数据,在某些情况下,重负载永远不会发生。

我做什么?

我问自己-这项任务是否通用?使用特定的插件/ gem是否可以完成数千次任务?如果是-MCV,否则-自己动手。

我喜欢使用MCV框架,以及如何更快地构建应用程序框架。对于简单的模型,我认为没有必要单独编写代码。我认为ORM库无法比我更好地生成复杂的SQL语句。对于复杂的查询,当涉及大量筛选和聚合时,我喜欢编写存储过程,对其进行调试和调整。