`

数据库驱动应用程序中影响性能的反模式

阅读更多

几乎所有现代应用程序都要通过数据库实现数据持久化。数据库访问层经常要对严重的性能问题负责。一旦遇到数据库的问题,大多数人开始研究数据库本 身。正确的索引和数据库结构对提高性能非常关键。然而,很多时候糟糕的性能或可伸缩性问题的罪魁祸首却是应用程序层,而不是数据库。

应用程序层控制并驱动数据库的访问。这一层的问题不能从数据库上得到补偿。所以要想得到高性能和扩展性,数据访问逻辑的设计非常关键。虽然数据库驱 动的应用程序中使用情况各不相同,但所有问题能够归结到几个反模式上。分析你的应用程序中是否使用了下列的反模式,并且解决他们,能够以最小的代价简单让 你的软件更快、 更稳定。

对象/关系映射的误用

对象/关系映射已经成为现代数据库应用程序的中心部分。对象/关系映射让人从面向对象软件中翻译和访问关系型数据的重担中解脱出来。它们向应用程序 人员隐藏了数据访问大部分的复杂逻辑。由于开发人员更专注于实际的业务逻辑,而不是基础架构细节,会使得生产效率更高。对象关系层不需要看到细节就可以轻 松操作复杂的对象图。这经常让人产生错误的印象,认为这些框架让人从设计数据访问逻辑的重担中解脱了出来。

开发人员经常认为数据访问框架很容易就把一切搞定了;然而,不理解内部工作机制就使用对象/关系映射框架,很多时候会导致程序性能低下。主要有两个误解引起了这些问题──加载的行为和加载的时间。

对象/关系映射基于每个对象加载数据。这意味着只有当一个对象被请求或者访问时,需要的SQL语句才会被创建并执行。这个原则非常普遍,乍一看多数情况下没问题。但同时它也常常是性能和扩展性问题的原因所在。

让我们看一个简单的例子。在一个存储地址信息的数据库中,我们有一张表存储人和一张表存储地址。如果我们想得到每个人的名字及其居住的城市,我们不 得不遍历人那张表,然后访问地址信息。下图显示了使用直接(out-of-the box)查询机制的结果。可以看出,这个简单的例子就导致了大量的数据库查询。

 

这直接引起了对象/关系映射中第二个重要的细节──加载时间。对象/关系映射-如果没有事先告知-会尽量晚地加载数据。这一行为就是延迟加载。延迟 加载保证了数据尽可能晚地加载,目的是执行尽量少的数据库查询,同时避免创建不必要的对象。虽然这个方法通常情况下是可行的,但当它访问那些没有加载的数 据,而数据连接已经不存在时,就可能导致严重的性能问题,以及所谓的LazyLoadingExceptions。

在如上所述的情况下,使用专门的数据查询能够显著提高性能。

因此,虽然对象/关系映射在数据访问的开发方面作用很大,设计合适的数据访问逻辑的重担仍然需要我们挑起。像dynaTrace这样带有工具的动态架构验证,能够帮助有效地识别程序中性能的弱点,并能主动解决。

加载了太多数据,实际不需要这么多

数据库访问中经常出现的另外一个反模式是加载了太多的数据,而实际上不需要这么多。导致这样的原因很多。快速应用程序开发工具提供了简单的方式,能 把数据结构和用户接口控制连接起来。由于数据层由领域对象构成,通常它们包含的数据要比实际显示的多得多。再次使用地址薄作为例子。这一次需要显示人的名 字及其居住城市。两个对象──地址和人──都被加载了,而不是只加载这3个字段。这导致了数据库、网络和应用程序层的大量开销。使用专门的查询能够大大减 少查询的数据量。然而这种性能的提升需要额外的工作去维护。表中新增一列可能需要对数据访问层修改多处。

 

设计的服务接口不合理也经常引起这种反模式。服务接口通常要设计的很通用,以支持大量的用例。其好处是各种各样的用例中都可以使用服务。另外,用例 要比后台服务实现变化的快得多。这会导致服务接口在某些场景下不适合。开发人员然后不得不使用一些补救方法,这可能导致数据访问逻辑效率低下。这个问题在 数据驱动的Web Services上经常出现。

为了克服这些问题,开发过程中需要不断地分析数据访问模式。如果是敏捷开发方法,每个用户故事完成后都应该检查数据访问逻辑。除此之外,应该跨应用程序用例分析数据访问模式,以理解数据访问逻辑,这样能够在开发中相应地优化数据访问逻辑。

未充分利用资源

数据库是应用程序中资源的瓶颈,所以使用越少越好。通常情况下大家对数据库连接的使用关注甚少。像任何共享的资源一样,数据库连接会严重影响整个系 统的性能。尤其是web应用和使用对象/关系映射框架并用了延迟初始化的程序,会让数据库保持连接的时间比需要的更长。处理开始时获得连接,直到页面生成 完成或者再也没有数据访问了才断开。在使用对象/关系映射的应用程序中,连接经常保持着以避免可恶的延迟初始化的问题。通过重新设计数据访问逻辑,把它从 后处理(比如页面生成)中分离出来,应用程序的性能和扩展性能得到极大的提高。

下图展示了10个并发数据处理线程的反应时间。第一个使用了1个数据库连接,第二个使用了2个连接,第三个使用了2个连接,但是有2/3的处理是在释放连接之后执行的。第三个场景数据访问经过更好的设计,仅用了1/10的资源就获得了几乎同样高的性能。

 

一刀切

一刀切是一种反模式,开发过程中经常见到,敏捷团队中则更多。这种反模式的特征是开发了主要功能之后,所有的数据访问就同样对待,好像它们没有任何区别。然而,区别对待不同类型的数据和查询可以显著提高应用程序的性能和扩展性。

应该对数据进行分析,考虑其生命周期的特性。它是否经常变化,它是可修改的还是只读的呢?数据的访问频率和访问模式,就隐含了一些潜在的代码,比如 可以做缓存。访问频率也暗含了一些线索,比如在哪里做优化更有意义。这可以避免过早进行优化以及不必要的优化,保证了性能调优效果最好。

对数据的使用模式进行分析也有助于调整数据访问层。理解真正使用了哪些数据有助于优化加载策略。比如,理解用户怎样浏览搜索结果对优化fetch size很有用。知道了用户是否查看订单详细信息可以给订单选择延迟还是立即加载。

除数据之外,查询也应该被分析并分类。重要的因素包括查询时间、执行频率、是否用于交互用户的上下文或者批量处理的场景中。事务特性有助于更好地调整查询的隔离级别。

比如,在同一个连接中运行用户短暂的交互查询和时间很长的报表查询,很容易导致终端用户的体验很糟糕。报表查询花费的时间很长,会占用大量的数据库 连接,让终端用户的查询无法拿到连接。通过给不同的查询类型使用不同的数据库连接池,会使终端用户的性能更可预测。降低数据库查询中不需要的隔离级别,也 能引起性能和扩展性的显著提高。

糟糕的测试

最后,缺少测试或者测试不正确是数据库访问应用程序性能和稳定性问题的一个主要原因。最近我曾就这一主题作了一个演讲,并询问听众是否把数据库访问 看作应用程序中一个性能问题。虽然他们都赞成,但没人有这样的测试流程,来测试数据访问的性能。所以虽然这个话题看上去是很重要,大家似乎都没有花时间去 做。然而,即使有测试流程,这也不一定说明测试就是正确的。虽然代码完成后能够立刻发现数据访问逻辑中的很多问题,但通常很晚之后才执行测试,比如负载测 试的时候。由于在生命周期的晚期才改动,可能需要修改架构,从而引起额外的开发和测试工作,这带来了很高的不必要的代价。

而且,必须设计一些测试用例,来测试真实世界的数据访问场景。测试数据访问必须在并发模式下进行,并且使用不同的访问类型。只有结合使用读/写访问才可能识别死锁和并发的问题。除此之外,输入的数据应该多种多样,以避免数据库访问时经常命中缓存,这是不切合实际的。

很多时候人们对预期的负载知之甚少,也不知道去测试哪些负载。很不幸的是,根据我的经验这种情况比比皆是。然而,不能把这当作借口,不定义负载和性能标准。要知道,定义一些标准比一点也不定义要好得多。

如果你对性能数据真的毫无头绪,最好是使用负载渐增测试法,逐步增加负载,直到达到了应用程序的最大值。这样你就知道了应用程序的负载峰值。如果负 载峰值既合理又现实,那就说明你做的不错。否则你得知道在哪方面提高性能。大多数情况下初始的测试表明,应用程序能够处理的负载要比期望的少得多。

结论

数据库访问是影响现代应用程序性能和可伸缩性的一个关键点。虽然框架支持构建数据访问逻辑,仍然需要对数据访问逻辑投入相当的精力,以避免种种陷阱和问题。问题之关键是要理解应用程序数据访问层的动态和特性的一切细节。

分享到:
评论

相关推荐

    jdbc连接数据库的方式2

     既然可以将Oracle的数据库作为一种面向对象的数据库来使用,就可以考虑将应用程序中的面向对象模式转到数据库中。目前的方法是创建Java bean作为伪装的数据库对象,将它们的属性映射到关系表中,然后在这些bean中...

    动态可扩展的数据库设计.docx

    如果用传统数据库设计模型,那么在设计初始阶段就必须 考虑到应用未来所有的改变及扩展,尽可能使表格的信息详尽,否 则当应用发生改变或扩展时,必须重新设计表结构,并对应用程序 中相关片段全部重写。如果同一...

    构建最高可用Oracle数据库系统 Oracle 11gR2 RAC管理、维护与性能优化

    14.3.5安全应用程序角色 14.3.6多规则认证例子 14.4本章小结 第15章 RAC稳定性与性能优化 15.1服务器硬件 15.1.1 Firmware固件升级 15.1.2硬件设备兼容性 15.1.3 FC HBA卡冗余 15.1.4 Infiniband技术 ...

    数据库系统应用开发方法.pdf

    影响因素:硬件资源、⽹络通信设备、操作系统环境、逻辑设计和物理设计质量、DBMS配置和性能、应⽤程序⾃⾝。 其他需求分析:存储需求(初始⼤⼩,增长速度)、安全性需求(安全控制级别,⽤户视图访问权限)、备份...

    自考数据库系统原理简答题总结.docx

    为应用程序加载、调用和卸载DB驱动程序。 4.ODBC的体系结构有多少层? ODBC的体系结构:1)ODBC数据库应用程序;2)驱动管理器;3)DB驱动程序;4)ODBC数据源; 5.什么是SQL/CLI? 在SQL标准中,称为"调用层接口...

    Android应用程序开发教程PDF电子书完整版、Android开发学习教程

    • 内容提供器(Content Providers)使得应用程序可以访问另一个应用程序的数据(如联系人数据库),或 者共享它们自己的数据 • 资源管理器(Resource Manager)提供 非代码资源的访问,如本地字符串,图形,和布局...

    Java数据库编程宝典3

    第10章 构建一个客户/服务器应用程序 10.1 使用不同的数据库和驱动程序 10.1.1 扩展的DBManager类 10.2 使用DatabaseMetaData 10.3 检索与数据库相关的信息 10.3.1 在JTree中显示DatabaseMetaData 10.4 检索...

    man-city:使用React构建的动态Firebase数据库驱动的网站

    使用React构建的动态Firebase数据库驱动的网站 Create React App入门 该项目是通过引导的。 可用脚本 在项目目录中,可以运行: npm start 在开发模式下运行应用程序。 打开在浏览器中查看它。 如果您进行编辑,则...

    Java数据库编程宝典2

    第10章 构建一个客户/服务器应用程序 10.1 使用不同的数据库和驱动程序 10.1.1 扩展的DBManager类 10.2 使用DatabaseMetaData 10.3 检索与数据库相关的信息 10.3.1 在JTree中显示DatabaseMetaData 10.4 检索...

    Java数据库编程宝典1

    第10章 构建一个客户/服务器应用程序 10.1 使用不同的数据库和驱动程序 10.1.1 扩展的DBManager类 10.2 使用DatabaseMetaData 10.3 检索与数据库相关的信息 10.3.1 在JTree中显示DatabaseMetaData 10.4 检索...

    UML和模式应用(架构师必备).part02.rar

    UML和模式应用(原书第3版) 原书名: Applying UML and Patterns : An Introduction to Object-Oriented Analysis and Design and Iterative Development (3rd Edition) 原出版社: Prentice Hall PTR 作者: ...

    UML和模式应用(架构师必备).part06.rar

    UML和模式应用(原书第3版) 原书名: Applying UML and Patterns : An Introduction to Object-Oriented Analysis and Design and Iterative Development (3rd Edition) 原出版社: Prentice Hall PTR 作者: ...

    Java数据库编程宝典4

    第10章 构建一个客户/服务器应用程序 10.1 使用不同的数据库和驱动程序 10.1.1 扩展的DBManager类 10.2 使用DatabaseMetaData 10.3 检索与数据库相关的信息 10.3.1 在JTree中显示DatabaseMetaData 10.4 检索...

    citrix 中文管理操作手册

    管理多个场中的应用程序及服务器 31 使用 Access Management Console 查看区域 31 管理用户会话和服务器进程 31 使用 Access Management Console 创建报告 31 使用 Access Management Console 配置应用程序访问权限 ...

    通过JDBC连接oracle数据库的十大技巧

     1、在客户端软件开发中使用Thin驱动程序 在开发Java软件方面,Oracle的数据库提供了四种类型的驱动程序,二种用于应用软件、applets、servlets等客户端软件,另外二种用于数据库中的Java存储过程等服务器端软件。...

    asp.net知识库

    在 ASP.NET 2.0 中创建 Web 应用程序主题 ASP.NET 2.0 中的数据访问 ASP.NET 2.0:弃用 DataGrid 吧,有新的网格控件了! 将 ASP.NET 2.0 应用程序服务配置为使用 SQL Server 2000 或 SQL Server 2005 ASP.NET 2.0 ...

    MongoDemo:在 Java 应用程序中连接 MongoDB 并为初学者从 Code 启动 MongoDb 服务器

    用 Java 连接 MongoDB关于 Mongo DB: MongoDB 是一个跨平台、面向文档的数据库,提供高性能、高可用性和易于扩展。...连接到 Mongo 数据库: MongoDB Java 驱动程序需要使用 Java 连接 MongoDB。 老

    UML和模式应用(架构师必备).part01.rar

    UML和模式应用(原书第3版) 原书名: Applying UML and Patterns : An Introduction to Object-Oriented Analysis and Design and Iterative Development (3rd Edition) 原出版社: Prentice Hall PTR 作者: ...

    MongoDB in action

    本书共分三部分,首先介绍mongodb 的历史、特性和使用场景,然后细致阐述mongodb api,专注于应用程序开发渐近式描述电子商务应用的模式与操作,并最后从dba 的角度考量性能和运维。另外,书中还介绍了面向文档...

    《剑指offer》Java基础-反射篇.pdf

    Java基础 反射篇 反射的思想及作用 反射的基本使用 获取类的 Class 对象 构造类的实例化对象 ...JDBC 加载数据库驱动类 反射的优势及缺陷 增加程序的灵活性 破坏类的封装性 性能损耗 反射基础篇文末总结

Global site tag (gtag.js) - Google Analytics