在数据库中编程 vs 在应用程序中编程

编程小白---数据库从零学起(1) Lesson1数据绑定:实现如图所示的简单功能,两个文本框内分别显示姓名和年龄。 操作步骤如下: 1.打开VS2013建立新项目--选择WPF应用程序--在界面上拖动两个TextBox,对两个TextBox重命名为TextName及TextAge。 2.新建一个名为Person的.cs的类,在其中建立两个方法: Public  string  Name{get;set;} 及Publi 阅读详情

原文地址 https://brandur.org/fragments/code-database-vs-app

数据库领域有一个长期存在的问题:你是更愿意将应用逻辑放在更接近数据库本身的存储过程和触发器中,还是置于数据库之上的应用程序代码中?

没有客观正确的答案,只有不同的观点。我浏览了 Stack Overflow 等地方的大量热门文章,并惊讶于普遍建议与常见事实的巨大差距。

可以肯定,大多数公司在应用程序代码中编写逻辑。开发者都不会想到编写存储过程,更不用说将领域逻辑放在存储过程中了。网络上很多人,却建议将逻辑放在数据库中。

先说个人观点:即使我因为类型、schema 和一致性而成为了关系数据库的拥护者,对把代码放到数据库中也还是持保留意见。将代码放入数据库,只在少数时候合适;即使合适,也要保持小规模、尽量少用。

对在数据库中编程的反对意见

数据库不适合应用程序编程的原因:

  • 不透明的后果

    一旦设置了触发器,如果不检查 schema,简单如插入一行的操作也可能产生严重的后果。

    同样的原因,我也反对 ActiveRecord callbacks 这类东西。

  • 调试、工具和测试

    对数据库内函数都比较困难。

    • 最多只能进行 printf 调试。
    • 很难使用开发者工具,比如用 LSP 完成代码(配置的噩梦 – LSP 必须主动与数据库交互,才能知道哪些关系和字段可用);SQL 函数会成为代码其他部分跳转到定义的死胡同。
    • 如果要(也应该)编写测试,就应该在应用程序代码中编写;这样…只要就地实现就可以了?

  • 部署和版本管理

    仍然可以对存储过程进行版本管理 – 只能通过编写新的迁移,就像数据库其他部分的版本管理一样。这就增加了更改代码的难度,毕竟部署其他应用代码肯定更容易。

    更改存储过程需要创建一个 CREATE OR REPLACE 函数,其中包含函数的整个实现(包括更改),这样就无法像使用 git blame 那样查看每行的历史记录。

  • 性能

    数据库逻辑与数据本身同在,所以有些情况下能提供最佳性能;但一些重要方面,却使性能更差:

    • 关系数据库通常是应用程序的单一阻塞点,其他应用程序代码部署在一组可以访问关系数据库的并行容器中。一个容器的应用代码容易扩展,只需部署更多的容器即可。数据库的扩展则比较困难。
    • 如果还需要运行数量未知的触发器,操作速度就会更慢。例如,当每一行都有一次隐藏触发,批量操作就要花费数倍时间。当然可以暂时禁用触发器,这就会失去触发器更多明显的好处。而且由于触发器不易被发现(参见上文「不透明的后果」),你可能无法明显感觉到操作速度变慢。

  • 程序化 SQL

    程序化 SQL 与 BASIC 和 COBOL 1 同属于最底层的编程语言,编写体验很糟糕,即使你熟悉。当然,可以激活扩展,从而使用其他语法更好的脚本语言,但你真的想让 Python 虚拟机在你的数据库中运行吗?

对在数据库中编程的支持意见

糟糕的意见

我在 Stack Overflow 上看到这样一些糟糕的论点:

  • 一致的实现:

    多个应用程序访问同一个数据库时,使用存储过程是保证它们使用相同实现的唯一方法。

    但出于多种原因,在应用程序之间共享数据库并不是好主意;在多个应用程序都可能向数据库写入数据的情况下共享数据库更糟(Schema 属于哪个程序?如何在 schema 变更时协调应用程序的部署?)。

  • 性能:

    存储过程的性能很高,因为它们与数据本身同位于数据库服务器上。

    这是事实,但依赖这一点很危险,因为数据库的可扩展性有限,任何利用这种局部性的做法都会给数据库带来很大压力。如上所述,将工作外包给可轻松扩展的应用程序代码会更安全、更具可扩展性。

  • ACID 一致性:

    触发器是保证 ACID 一致性的唯一方法。

    在一个看起来都是数据库专家的网站上发现这一点很奇怪。——并不是唯一的方法,不然为什么有数据库事务?

更好的意见

最后,有几个更好的理由支持将代码放在数据库中:

  • 非常适合一些小而受限的模块:

    有一小部分常见模块非常适合触发器。例如一个很小的函数,用来触发表上的 updated_at 时间戳:

    CREATE OR REPLACE FUNCTION set_updated_at()
    RETURNS trigger
    AS $$
    BEGIN
    		NEW.updated_at := current_timestamp;
    		RETURN NEW;
    END
    $$ LANGUAGE plpgsql;
    

    然后数据库中的每张表都会有这个触发器:

    CREATE TRIGGER team_set_updated_at
    	BEFORE UPDATE ON team
    	FOR EACH ROW
    	EXECUTE FUNCTION set_updated_at();
    

    在应用程序代码中可以实现这一点(使用类似模型回调的方法),但会带来大量重复,一旦在某处遗漏就会造成错误。相比之下,数据库版本的运行更可靠,效果也更好。

  • 实现深度一致性,避免操作错误:

    举个例子:假设我们有两个独立的账户表,一个是在我们这里注册的账户,另一个是通过身份提供商的 SSO 进入的账户。它们有很大区别,因此我们要分别跟踪;但它们是相关的概念,账户可能拥有的资源(如 API 密钥)可能由其中一种类型或另一种类型拥有。

    另一个名为 account_common 的表通过两个小操作增强一致性:

    • 确保两个不同类型的账户不会意外共享一个 ID
    • 充当通用资源(如 API 密钥)的外键目标

    在添加账户或 SSO 账户时,要确保为其插入 account_common 记录。在应用程序代码中插入额外的记录不方便且容易忘记,因此我们用一个简单的触发器:

    CREATE OR REPLACE FUNCTION account_common_upsert() RETURNS TRIGGER AS $$
    		BEGIN
    				INSERT INTO account_common (
    						id, kind
    				) VALUES (
    						NEW.id, TG_TABLE_NAME
    				)
    				ON CONFLICT (id, kind)
    				DO NOTHING;
    
    
    				RETURN NEW;
    		END;
    $$ LANGUAGE plpgsql;
    
    
    CREATE TRIGGER account_common_upsert BEFORE INSERT ON account
    		FOR EACH ROW EXECUTE FUNCTION account_common_upsert();
    CREATE TRIGGER account_common_upsert BEFORE INSERT ON sso_account
    		FOR EACH ROW EXECUTE FUNCTION account_common_upsert();
    

这些情况仍然存在上述数据库代码的缺点,但也是将其放入数据库的好处大于成本的地方。

总之,应该根据具体情况评估,使用时将代码保持在较小的范围内。


💡 更多资讯,请关注 Bytebase 公号:Bytebase

Azure数据库服务比较:SQL Database vs Cosmos DB 结构化数据场景:如订单管理、用户认证等需要强事务支持的业务非结构化/半结构化场景:如物联网设备日志、社交网络数据、实时推荐系统:基于传统关系型数据库(SQL Server)的云原生服务,支持ACID事务和复杂SQL查询Cosmos DB:全球分布式NoSQL数据库,支持多模型(文档、键值、图、宽列)和弹性扩展两者的架构设计哲学有何本质区别?数据建模和查询语言的差异如何影响开发体验?一致性、可用性、吞吐量的权衡模型如何选择?典型业务场景下的选型决策依据是什么?技术原理对比。 阅读详情

相关推荐

数据仓库系列 1:什么是数据仓库,它与传统数据库有什么不同?

数据仓库(Data Warehouse)是一个面向主题的、集成的、相对稳定的、反映历史变化的数据集合,用于支持管理决策。这个定义来自被誉为"数据仓库之父"的Bill Inmon。但这个定义可能对初学者来说有点抽象,让我们通过一个类比来更好地理解它:想象你是一家大型超市的经理。每天,你的超市都会产生大量的交易数据:销售记录、库存变化、客户信息等。这些数据分散在不同的系统中:收银系统、库存管理系统、会员管理系统等。

一个8年大数据开发工程师的碎碎念 3389

VS2013 MFC ODBC连接SQL SERVER数据库编程(二)

VS2013 MFC ODBC连接SQL SERVER数据库编程(二) 转载请注明:http://blog.youkuaiyun.com/my_acm/article/category/2616577 在上一篇中,我已经说明了如何连接SQL SERVER数据库 下面参考http://wenku.baidu.com/link?url=h1rGgnhSmnclH2lFexHmlP_SZ2LUDR

my_acm 1万+

VS Code 4款数据库插件对比:SQLTools vs Database Client vs DBCode vs MSSQL

本文深入评测了VS Code中四款主流数据库插件:SQLTools、Database Client、DBCode和MSSQL,从功能完整性、性能开销、易用性和多数据库支持等维度进行对比分析。针对不同开发需求提供选型建议,帮助开发者高效管理MySQL等数据库,提升工作效率。

weixin_26833139的博客 395

vs2008 MFC访问Access 2010数据库

MSDN给出了各种语言访问Access 2010的详细介绍:点击打开链接。下图列出了各种语言访问Access 2010的接口。 我在VS2008下使用MFC下的ODBC相关接口访问Access 2010数据库。 Demo中使用MFC访问数据库accsess2010数据库AccessDemo.accdb下有student表,表中有用户编号、电话号码、姓名、省份四列信息,表中有包含这四列信...

xuela-net 477

1、探索C与Visual Studio.NET:构建现代应用程序的基础

本文深入介绍了如何使用C#语言和Visual Studio.NET开发工具构建现代应用程序,涵盖事件驱动编程、Windows桌面应用、Web应用、数据库操作、Web服务、移动应用开发以及Crystal Reports报表生成等内容,为开发者提供了全面的技术指导和实践建议。

terraform7cloud的博客 212

从数据库到数据仓库:数据仓库导论

本文为数据仓库导论,旨在介绍数据仓库的基本理念和应用场景,帮助读者理解数据仓库的重要性及其在企业中的实际应用。

探索大数据世界 - 深入解析数据存储、分布式计算与人工智能 2787

数据仓库和数据库的区别

本文主要介绍数据仓库和数据库的区别,首先描述下数据仓库是什么: 数据仓库的本质还是一个数据库,它将各个异构的数据源数据库的数据给统一管理起来,并且完成了质量较差的数据的剔除、格式转换,最终按照一种合理的建模方式来完成源数据组织形式的转变,以更好的支持到前端的可视化分析。 数据仓库中主要存储的是结构化的数据,但是它的来源可以是多种类型的数据来源(结构化、半结构化、非结构化),中间需要一个ETL过程。 一、用途 数据库:主要用于事务处理,即OLTP(Transaction),也就是我们常用的面向业务的增删改查操

啥也不是 2万+

华为硬件逻辑岗笔试题(一)

积少成多,集腋成裘,坚持!!! 目录 1. 进制转换 2. 状态机和编码方式 3. 存储器的分类 4. Verilog语法中的操作符 5. 对组合逻辑的认识 6. 对时序逻辑的认识 7. 竞争冒险的认识 8. 基本时序逻辑电路 9. 建立时间和保持时间 10. 同步时序电路 11. 组合逻辑和时序逻辑判断 13. 基本总线的理解 14.加法器 15.FPGA开发工具 1. 进制转换 1、十进制46.25对应的二进制表达式为( )。 A 101110.11...

qq_42235129的博客 1万+

Vs2012如何创建数据库

以前一直用的是vs+sqlserver的配置,这次有学长问我vs2012自带数据库吗?想都没想就说带,结果就让我找怎么建数据库,结果还真被我找到了。创建方法如下 首先在你所建的工程上单机右键选择添加-添加新建项 然后在里面找到sqlserver数据库 改成自己想要的名字,然后vs会未响应一段时间,之后就会自动连接到数据库了 Vs会自己在web.config...

weixin_30485799的博客 997

WandB本地部署踩坑指南:从Docker启动到License更新的完整流程(附常见错误解决方案)

本文详细介绍了Weights & Biases(WandB)机器学习实验管理平台的本地化部署全流程,涵盖从Docker环境搭建、许可证管理到常见错误排查的实战经验。针对企业级应用场景,文章还提供了性能优化、高可用架构设计及开源替代方案Trackio的评估与迁移策略,为构建安全、可控的内部实验追踪平台提供完整解决方案。

potato的博客 568

中科蓝讯蓝牙耳机SDK实战:从目录解析到消息处理框架

本文深入解析中科蓝讯蓝牙耳机SDK的目录结构与消息处理框架,提供从硬件驱动到蓝牙功能定制的实战指南。重点剖析SDK核心模块如消息队列机制、按键事件处理及电量报告优化,并分享二次开发中的调试技巧与避坑经验,助力开发者高效完成TWS耳机功能定制。

weixin_30335575的博客 389

Database数据库 vs Data Warehouse数据仓库 vs Data Mart数据集市 vs Data Lake数据湖

简单易懂~图文并茂~ Database数据库 vs Data Warehouse数据仓库 vs Data Mart数据集市 vs Data Lake数据湖

喻师傅的学习笔记 1901

健康保险费用预测:可解释机器学习在精算建模中的实战落地

健康保险费用预测是医疗AI与保险科技交叉领域的核心任务,本质是基于临床变量与社会因素对个体医疗支出进行风险量化。其技术原理需兼顾统计建模能力与监管可解释性,XGBoost+SHAP组合因支持特征归因、边际效应分析和临床可干预推演,成为保险精算场景的主流选择。该技术显著提升保费定价精度、降低偿付风险,并支撑DRG费用预警、团险核保辅助及再保险尾部风险评估等关键应用。本文聚焦真实产线中的时间序列验证、临床分层特征工程与监管红线指标(如Bias@90th、Calibration Slope),深入解析如何让模型不

weixin_33702545的博客 306

一文了解数据库vs数据仓库vs数据湖

在实际工作中,我们应该如何选择使用OLTP数据库还是OLAP数据仓库还是数据湖呢?有些同学会追求时髦前沿技术,不管业务需求是什么样的,直接就上数据湖架构,这样其实是一种不负责任的表现,单纯的以自己实践为主,业务需求为次的行为。这时候就需要架构师来评估具体业务的场景以及未来发展(2-3年)来看,最适合的架构模型是那种,而不是直接就上新技术,一般技术在2-3年会有一个迭代周期,你无法保证现在选择的技术栈未来看就是最优的。那么我建议从一下几个方面来进行选择

分享云原生大数据技术和个人成长、职业发展相关内容 1458

# 多用户 JupyterHub 配置教程(通用 Linux 服务器版)

以上即是通用 Linux 服务器上的多用户 JupyterHub 实战配置。从安装认证与 Spawner 选择自动创建系统用户到反代与运维,覆盖了小团队到中等规模的主流场景。根据团队增长与合规要求,你可以进一步引入、统一身份源(LDAP/OAuth2/Keycloak)与资源配额治理,平滑演进到企业级部署。

数字化老司机 1291

手把手教你用AppsFlyer SDK实现延迟深度链接(附Android/iOS代码示例)

本文详细介绍了如何使用AppsFlyer SDK实现延迟深度链接,提供Android和iOS双平台代码示例,帮助开发者解决跨平台精准跳转与用户归因问题。通过实战案例和高级场景分析,提升应用的用户转化率和广告投放效果。

sre5engineer的博客 704

vs2008连接access数据库的问题

<param value="true" name="allowfullscreen"><param value="http://wenku.baidu.com/static/flash/apireader.swf?docurl=http://wenku.baidu.com/play&docid=502fe0621ed9ad51f01df21b&title=VS2010%E5%8

sf_suifeng的专栏 589

opencode : 无法将“opencode”项识别为 cmdlet、函数、脚本文件或可运行程序的名称 解决方案

本文主要介绍了opencode : 无法将“opencode”项识别为 cmdlet、函数、脚本文件或可运行程序的名称解决方案,希望能对使用opencode的同学们有所帮助。 文章目录 1. 问题描述 2. 解决方案

weixin_43178406的博客 11万+

数据库 vs 数据仓库

数据库和数据仓库并不是非此即彼的关系,其实是数据管理进化的两个阶段。随着业务的发展,可能需要将多个操作型数据库中的数据集成到一个统一的数据仓库中,以提供全面的业务视图。数据仓库通常包含历史数据,这有助于分析趋势和模式,而操作型数据库通常只保留当前数据。数据仓库针对分析查询进行了优化,而操作型数据库则针对事务处理进行了优化。数据仓库提供了数据的高层次抽象,使得非技术用户也能容易地进行数据分析。

weixin_43156294的博客 1438

LDRA Testbed软件静态分析_常见问题及处理

通过前面的几篇文章,LDRA Testbed软件静态分析的内容基本讲解完了,本篇文章将针对使用Testbed进行软件静态分析的常见问题进行介绍。 到此为止,LDRA Testbed软件静态分析的内容已经全部讲完,如果有问题,欢迎私信提问(不经常登录,回复可能不及时,见谅)。下一篇文章将开始讲解如何使用Testbed进行单元测试。

文章主要涉及嵌入式软件开发、测试、项目管理等,欢迎交流,共同进步。 2591

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

聊聊数据库vs数据仓库vs数据湖

又会有男装、女装、童装,在选择男装之后呢?有些同学会追求时髦前沿技术,不管业务需求是什么样的,直接就上数据湖架构,这样其实是一种不负责任的表现,单纯的以自己实践为主,业务需求为次的行为。其实,细心的观察会发现,在整个架构演进过程中不仅仅是离线、实时两个计算场景的演进,在存储层也在不断演进,从最开始的单纯离线数仓以结构化存储为主、后来实时+离线数仓存储以流+结构化存储为主,再后来计算和存储分离,计算层更加轻量化,而且计算天然是无状态的,存储可以灵活的选择不同的介质,所以,整个数据存储以半结构化、结构化为主。

分享云原生大数据技术和个人成长、职业发展相关内容 892

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

数据库, 数据仓库, 数据集市,数据湖,数据中台

转载声明 本文大量内容系转载自以下文章,有删改,并参考其他文档资料加入了一些内容: 数据仓库和数据集市的区别 作者:修鹏李 出处:优快云 大数据:数据仓库和数据库的区别 作者:南宫蓉 出处:简书 第一篇:数据仓库概述 第二篇:数据库关系建模 作者:穆晨 出处:CNBLOS 摘要 本文简要介绍数据库 数据仓库和数据集市概念,并做简要对比。 0x01 数据仓库和数据库 1.1 数...

迷路剑客个人博客 1万+

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

数据库 vs 数据仓库:傻傻分不清?一文搞懂它们的本质区别

数据库解决“发生了什么”的问题数据仓库解决“发生了什么趋势”的问题它们就像前线士兵和后方参谋,只有配合得当,才能真正发挥数据的价值。 数据仓库的核心价值在于“整合”与“共享”,SQL2API 是一种低代码的数据服务能力,它允许开发者或数据分析师通过一条 SQL 语句,快速生成对外可访问的 API 服务,以实现数据仓库中的轻量级数据共享,典型的比如麦聪QuickAPI。

lgbingyu00的博客 2363

VS2013 API方法连接 64位 MySQL56

学习使用vs2013进行mfc连接mysql56

zhkmxx930的专栏 724

Database Client:一款流行的VS Code数据库客户端插件

它把多种数据库的连接、查询、管理都整合到了同一个编辑器中,不用切换工具,能提升不少开发效率。Visual Studio Code 内置了一个功能强大的扩展市场,可以查找、安装及管理所需的扩展插件。

Tony.Dong的专栏 3125
上一篇: 五个迹象表明你辞职时机已到
下一篇: Bytebase & CloudCanal 联合解决方案
Bytebase
博客等级 码龄5年 1349粉丝 258原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值