作为一名CRUD开发人员,需要做出的权衡之一是决定在服务器上的SQL中应该完成多少工作,以及在代码中应该在客户端完成多少工作。 / p>
您如何确定支点的位置?您的决定有哪些因素?你犯了什么样的错误?什么效果很好?
[编辑]我对这个问题的回答率很低,我感到很惊讶。我认为这是所有CRUD编程的基本问题。设置余额的方法是在性能和可维护性之间进行权衡。
我没有真正考虑过的另一个问题是域名变化不足,答案可能需要在每个域的部分表达。这就是我在答案中尝试做的事情。
答案 0 :(得分:43)
我的优先事项:
尽量减少数据库出行。 如果可能,代码应该完成大部分工作,并且只在必要时才访问数据库。如果是这样,它应该尽可能多地获得当前操作。
最大限度地降低SQL复杂性。 即使我们应该少访问数据库,这并不意味着构建一个过于复杂的SQL查询,这个查询不具备性能并且做得太多。仍然需要维护查询,如果两个更简单的查询将节省开发和维护一个大型查询的麻烦,那么应该使用额外的代码而不是更多的数据库工作。
最小化代码列表迭代。 代码很棒。一个放置业务逻辑的好地方,以及许多整洁的库函数。代码很棒。但是如果使用代码意味着必须通过从数据库返回的列表反复迭代,其中一些简单的数据库where子句或连接可以消除该工作,那么SQL需要改进,并且代码最小化。
< / LI> 醇>一般情况视具体情况而定。对于长寿命的应用程序,维护是一项巨大的成本,简单性通常会决定我的设计。
答案 1 :(得分:20)
数据库是一个容纳数百万行表的地方,可以有效地对这些表进行读写。
数据库不是执行字符串操作或日期逻辑的地方。它不是计算余额或生成邮件的地方。使用其他工具(例如代码)可以更好地解决这些问题。
答案 2 :(得分:9)
任何与数据完整性相关的内容都应该在数据库中完成。原因是数据可能受到多种来源的影响,而不仅仅是用户界面。因此,数据库应存储关键关系,对字段中允许的数据的约束,默认值等。如果约束对于常规约束而言过于复杂,则必须触发。应仔细考虑数据类型,并以某种方式作为约束。如果数据旨在用于数学计算,则应使用某种类型的数值数据类型(不是浮点数或实数),数据是日期,始终使用日期时间数据类型来存储非日期。如果数据是数字但不是用于数学计算(例如SSN),则将其存储在字符串类型的数据中,但对其进行约束以确保存储的所有值都是数字。
这并不意味着您在发送之前不应检查它是否是GUI中的有效日期。您应该对GUI发送到数据库的数据执行检查,以避免发送不会插入的数据,但应始终设置数据库以防止插入不正确的数据,无论它是如何发送的。没有任何意义上浪费宝贵的网络和数据库资源来处理已知的不良数据。
报告聚合通常可以在GUI上更快地完成,但是如果需要返回太多记录,则最好在数据库端执行,或者您应该创建OLAP报告数据库以提高速度。
答案 3 :(得分:6)
这不是SQL vs. Code问题,而是更多的Client vs. Server问题。客户端/服务器的整体思想是让服务器以集中的方式为客户端提供服务。在实践中,这意味着:
所涉及的许多问题都可以在其他设计领域找到,例如面向对象的设计。为其他类提供服务的类应该封装功能,并且只公开其客户端所需的内容。 SQL服务器也是如此。如果您认为SQL服务器仅仅是一个数据检索系统,那么您就没有采取适当的优势。
实际节省包括:最小化通过网络发送的数据;集中/标准化处理;允许更改而无需重新部署客户端软件;改善了表现。
至于准确划线的地方......没有神奇的答案。真正的答案是数据库模式+存储过程+视图定义了一个API,良好的API设计并非易事,但值得麻烦。使用信息隐藏,封装,内聚以及您在其余编程和设计工作中使用的所有其他内容等原则。它们在这里是合适的。
答案 4 :(得分:4)
尽可能少地访问数据库。
如果您最终放弃从数据库中检索到的数据,则需要重新设计查询并使其更具体。
该脚本负责操作数据,除非存在使数据库更容易使用的索引。
数据库应该能够在没有脚本的情况下存在。 Cron作业很好,但如果脚本在特定时间没有执行,数据库应该能够存活。
永远不要在循环中放置查询。总有一种方法可以在一个查询中生成相同的结果(也称为连接)。
数据库仅用于保存和检索原始数据。保留脚本的任何格式或数学。
总而言之,尽可能少地强调数据库。尽可能少地使用与数据插入和检索相关的查询。使脚本承担更多的负载,并确保数据库不是第一个下载的。
答案 5 :(得分:4)
我尝试在数据库中做数据库事务。所以,排序,分组,过滤。这都是在查询中完成的(通常是一个sproc)。我使用代码来执行查询,然后对代码执行任何我们需要的操作。我还尝试使用“获取数据一次,只有一次”的心态,以便减少到服务器的往返行程。
答案 6 :(得分:4)
在我看来,如果它直接处理数据,那么它应该在数据库中完成;如果它处理业务逻辑,它应该在代码中完成。
例如,按特定字段过滤数据应该由数据库决定。要在报告上显示的汇总总数应在数据库中完成。与数据相关的次要逻辑(例如强制执行数据完整性的触发器)应该在两者中完成(不要为我发表评论!)以确保您的应用程序是安全的。
实际业务逻辑(例如,如果订单总额超过500美元,则应用折扣)应在代码中完成,并且最终值仅存储在数据库中。但是,如果折扣金额因客户类型而异,那么折扣金额应存储在数据库中,而不是存储在计算中的逻辑。
答案 7 :(得分:3)
你有哪些:
OR
如果上面的答案是数据库开发人员是你的强项,那么在数据库中完成工作。一个非常好的数据库人可以提供功能,因此您的代码可以简单易用。可能需要多次往返(在某些情况下可能会成为杀手)但性能可能非常好。最大的问题是,周围没有很多真正有才华的DB人。
如果编码是您的强项,请保持数据库简单并使用超级简单的参数化查询来获取和更新您的数据库。当你碰到瓶颈时,只能使用触发器和存储过程之类的东西。您必须具备数据库管理方面的一些技能。决定索引和维护这些索引等基本内容。还知道何时进行标准化以及何时进行标准化。
答案 8 :(得分:3)
取决于应用程序的类型。如果应用程序是唯一使用数据库的应用程序,那么代码就是主数据库。如果DB可能比应用程序寿命更长,那么尽可能使用DB。
答案 9 :(得分:2)
我在商业界做了10年以上的CRUD编程顾问。我可以告诉你,我把业务逻辑放在了sprocs&amp;尽我所能(并且有意义)。每次风吹都需要改变,而数据库中的逻辑使得改变变得容易,并且(通过体面的评论)它是自我记录的。加上sprocs可以提高安全性并简化代码重用。在商业中,sprocs ARE 应用程序。
答案 10 :(得分:2)
SQL是专门用于处理数据集的专用代码,例如排序,过滤和连接。我认为“SQL vs. CODE”是一个误导性的问题。相反,我建议将您的问题视为多种专业语言之间的选择。对于这个答案,我将使用术语“服务器端”来引用SQL代码,使用“客户端”来引用以不同的,更通用的语言编写的所有内容。
根据我的经验,客户端代码更容易编写和维护,因为(1)我倾向于更熟悉客户端语言和工具,(2)客户端开发往往有更好的工具,编辑器和源代码控制集成,以及(3)维护更容易,因为我只需要在一个地方寻找逻辑。所以,我更喜欢编写客户端代码而不是服务器端代码,除非我有其他令人信服的理由。
但是,服务器端代码以SQL语句的形式对于充分的性能至关重要。连接,过滤和排序数据几乎总是属于SQL,因为数据库将比在客户端更快更容易地完成。根据经验,如果我正在编写使用SQL游标来过滤或排序记录集的代码,我可能做错了,应该将该逻辑移到SQL中,它会更快,更容易编写,更容易理解。
答案 11 :(得分:2)
我对代码与sql的决定通常取决于哪个似乎是最简单/最快的实现。一旦它在那里,我继续前进。后来,如果看起来它应该被移动,它就会被移动。 &LT; 耸肩&GT;尽管如此,我尽量不要过多地冒汗。
如果它与数据库密切相关 - 尤其是涉及大量使用数据库记录的东西 - 那么进入sql是有意义的。如果它与应用程序紧密相关,它会去那里。
答案 12 :(得分:1)
答案取决于所涉及的开发人员的实力。最后,您需要提高工作效率,因此您必须在解决当前问题与长期维护考虑因素之间取得平衡,同时考虑到您的团队可能是所有应用程序开发人员,而不是SQL重量级人员。
你将如何向团队传达变化,以及每个人能够理解的角色与角落里的家伙相比,你将会在接下来的几年中扮演天才角色?如果您的代码有错误,那么每个团队成员能够多快地找到问题的根源?
所有“管理层都说”,其他人在这里详述的基础知识我也会回应:
答案 13 :(得分:1)
因为我的代码在我的客户端计算机上运行,并且我不想仅仅为了更新我的代码而需要数据库管理员访问权限,所以除了数据之外,我几乎没有在数据库中放置任何内容。
答案 14 :(得分:1)
对我来说,由于技术限制,数据库是必需的:主存储器很小并且不会持久存在。所以对我而言,任何与持久性无关的东西都在代码中,只有当我需要来回获取数据时,我才会求助于SQL(实际上甚至不是这样,我的DAL为我做了这一点)。
答案 15 :(得分:1)
我们使用.NET 3.5和LINQ to SQL - 所以我们是100%的代码,根本没有手写SQL。这是幸福!
答案 16 :(得分:1)
以下是我会考虑的一些权衡因素:
......如果我想到其他任何事情,我会告诉你的。
答案 17 :(得分:1)
我关于何时使用sql的规则:
循环记录集时不要进行数据库调用。
保持逻辑在一起。
想想那些落后于你的其他开发者。把它写在最清楚的地方。
答案 18 :(得分:1)
答案 19 :(得分:1)
平衡是您获得最高可维护性且可接受的性能。
所有业务逻辑都应该在应用程序中完成。您可以从Sql Server开始,但是如果策略更改为Oracle。您只需将数据迁移到Oracle,无需重写任何代码。
或者某些应用程序,必须支持多个db,所以你刚刚在app中完成了所有代码。当您遇到问题时,您只需在应用程序中修复问题。无需修复多个数据库中的问题。
为此,必须在应用程序中生成所有CRUD代码。这意味着你需要一个好的ORM框架(Linq,Hibernate)来完成这项工作。
答案 20 :(得分:0)
如果在SQL中执行此操作使其更易于管理,请在SQL中执行。如果在代码中执行此操作使其更易于管理,请在代码中执行。
答案 21 :(得分:0)
在我们小组中有几个案例。
INSERT / SELECT
可以满足的处理通常我们让程序根据用户提供的参数编写插入选择,然后在服务器上执行
控制中断处理
程序使用所需的顺序构建select,并在服务器的上下文中执行它。结果集被吸回到程序中,并逐行处理为控件中断。
复杂处理
程序构建select,并在服务器的上下文中执行它。结果集被逐行回送到程序,在那里进行代码密集处理。结果将转移到文件或UPSERT返回数据库。
效果严重
程序构建select,在服务器的上下文中执行它。完整的结果集被吸回到内存中,在内存中进行代码密集型处理。 生成的已处理信息将进入文件,或者UPSERTED返回数据库。
答案 22 :(得分:0)
根据我的经验,与SQL相比,在代码中执行复杂的数据验证更容易,因此答案取决于应用程序的类型和我正在处理的数据。如果必要的验证是相当良性的,那么我就可以以存储过程的形式将这个逻辑放在数据库层中。
然而,当需要升级您的应用程序时,会出现这种方法的一个明显缺点。与客户端代码的更改相比,对模式的更改实施起来更具挑战性,特别是如果您要向客户端发送代码而不是开发内部使用的应用程序。
此外,与执行应用程序代码的构建相比,通常需要更多工作来组合更改脚本以进行数据库架构更改(例如,识别已更改的对象,使更改脚本具有幂等性)。这主要是由于数据库开发方面的工具(或缺少工具)。
答案 23 :(得分:0)
通常在我参与过的项目中,大部分数据都是由数据库服务器处理的,大部分的演示都是用代码完成的。
例外是这样的: SELECT col1,col2,col3 从表
演示文稿是: col1,col2,col3,col1 / col2,col1 / col3,...
如果我得到一个等式中的所有操作数,我会在代码中执行,如果没有,我会将其作为查询的一部分(选择col1,col2,col1 / col4 ......)
答案 24 :(得分:-1)
以下是我听到的一些建议:如果项目的预算低于100万美元,请将SQL语句放在客户端代码中。如果预算超过100万美元,请创建访问者类等。请参阅此blog post。我不知道我是否同意具体的金额,但我同意预算(以及隐含的项目规模,重要性等)应该影响您在发展中的正式程度。
答案 25 :(得分:-1)
我将SQL用于查询(声明性),将Python用于过程(逐步操作)。