inverse = ?
inverse=false(default)
用于单向one to many关联
parent getChildren() add(child) // insert child
parent getChildren() delete(child) // delete child
inverse=true
用于双向one to many关联
child setParent(parent) session save(child) // insert child
session delete(child)
在分层结构的体系中parentDao childDao对于CRUD的封装导致往往直接通过session接口持久化对象 而很少通过关联对象可达性
To be the best IT munity
one to many关系单向关系还是双向关系?
parent getChildren() add(child)对集合的触及 *** 作会导致lazy的集合初始化 在没有对集合配置二级缓存的情况下 应避免此类 *** 作l select from child where parent_id = xxx 性能口诀
一般情况下避免使用单向关联 尽量使用双向关联l 使用双向关联 inverse= true
在分层结构中通过DAO接口用session直接持久化对象 避免通过关联关系进行可达性持久化
To be the best IT munity
many to one关系
单向many to one表达了外键存储方 灵活运用many to one可以避免一些不必要的性能问题
many to one表达的含义是 ……n many可以是 可以是 也可以是n 也就是说many to one可以表达一对多 一对一 多对一关系 因此可以配置双向many to one关系 例如 l 一桌四人打麻将 麻将席位和打麻将的人是什么关系?是双向many to one的关系To be the best IT munity
one to one通过主键进行关联相当于把大表拆分为多个小表例如把大字段单独拆分出来 以提高数据库 *** 作的性能Hibernate的one to one似乎无法lazy 必须通过bytecode enhancement To be the best IT munity
集合List/Bag/Set one to many l List需要维护index column 不能被用于双向关联 必须inverse= false 被谨慎的使用在某些稀有的场合l Bag/Set语义上没有区别l 我个人比较喜欢使用Bag many to many l Bag和Set语义有区别l 建议使用Set To be the best IT munity
集合的过滤l children = session createFilter(parent getChildren() where this age > and this age < ) list()
针对一对多关联当中的集合元素非常庞大的情况 特别适合于庞大集合的分页 l session createFilter(parent getChildren() ) setFirstResult( ) setMaxResults( ) list() To be the best IT munity
继承关系当中的隐式多态HQL from Object l 将把所有数据库表全部查询出来l polymorphi = implicit (default)将当前对象 和对象所有继承子类全部一次性取出l polymorphi = explicit 只取出当前查询对象To be the best IT munity
Hibernate二级缓存著名的n+ 问题 from Child 然后在页面上面显示每个子类的父类信息 就会导致n条对parent表的查询
l select from parent where id = ?
l …
l select from parent where id = ?
解决方案
eager fetch
二级缓存
To be the best IT munity
inverse和二级缓存的关系当使用集合缓存的情况下
inverse= false 通过parent getChildren()来 *** 作 Hibernate维护集合缓存l inverse= true 直接对child进行 *** 作 未能维护集合缓存!导致缓存脏数据
双向关联 inverse= true 的情况下应避免使用集合缓存To be the best IT munity Hibernate二级缓存是提升web应用性能的法宝OLTP类型的web应用 由于应用服务器端可以进行群集水平扩展 最终的系统瓶颈总是逃不开数据库访问 哪个框架能够最大限度减少数据库访问 降低数据库访问压力 哪个框架提供的性能就更高
针对数据库的缓存策略
对象缓存 细颗粒度 针对表的记录级别 透明化访问 在不改变程序代码的情况下可以极大提升web应用的性能 对象缓存是ORM的制胜法宝
对象缓存的优劣取决于框架实现的水平 Hibernate是目前已知对象缓存最强大的开源ORM
查询缓存 粗颗粒度 针对查询结果集 应用于数据实时化要求不高的场合To be the best IT munity应用场合决定了系统架构一 是否需要ORM Hibernate or iBATIS?
二 采用ORM决定了数据库设计
Hibernate
倾向于细颗粒度的设计 面向对象 将大表拆分为多个关联关系的小表 消除冗余column 通过二级缓存提升性能(DBA比较忌讳关联关系的出现 但是ORM的缓存将突破关联关系的性能瓶颈) Hibernate的性能瓶颈不在于关联关系 而在于大表的 *** 作
iBATIS
倾向于粗颗粒度设计 面向关系 尽量把表合并 通过表column冗余 消除关联关系 无有效缓存手段 iBATIS的性能瓶颈不在于大表 *** 作 而在于关联关系
To be the best IT munity性能口诀
使用双向一对多关联 不使用单向一对多
灵活使用单向多对一关联
不用一对一 用多对一取代
配置对象缓存 不使用集合缓存
一对多集合使用Bag 多对多集合使用Set
继承类使用显式多态
lishixinzhi/Article/program/Java/ky/201311/28385
具体来说,本文包括以下内容:
事务
查询性能
用户和查询冲突
容量
配置
NoSQL 数据库
事务
事务可以观察真实用户的行为:能够在应用交互时捕获实时性能。众所周知,测量事务的性能包括获取整个事务的响应时间和组成事务的各个部分的响应时间。通常我们可以用这些响应时间与满足事务需求的基线对比,来确定当前事务是否处于正常状态。
如果你只想衡量应用的某个方面,那么可以评估事务的行为。所以,尽管容器指标能够提供更丰富的信息,并且帮助你决定何时对当前环境进行自动测量,但你的事务就足以确定应用性能。无需向应用程序服务器获取 CPU 的使用情况,你更应该关心用户是否完成了事务,以及该事务是否得到了优化。
补充一个小知识点,事务是由入口点决定的,通过该入口点可以启动事务与应用进行交互。
一旦定义了事务,会在整个应用生态系统中对其性能进行测量,并将每个事务与基线进行比对。例如,我们可能会决定当事务的响应时间与基线相比,一旦慢于平均响应时间的两个标准差是否就应该判定为异常,如图1所示。
图1-基于基线评估当前事务响应时间用于评估事务的基线与正在进行的事务活动在时间上是一致的,但事务会由每个事务执行来完善。例如,当你选定一个基线,在当前事务结束之后,将事务与平均响应时间按每天的小时数和每周的天数进行对比,所有在那段时间内执行的事务都将会被纳入下周的基线中。通过这种机制,应用程序可以随时间而变化,而无需每次都重建原始基线;你可以将其看作是一个随时间移动的窗口。
总之,事务最能反映用户体验的测量方法,所以也是衡量性能状况最重要的指标。
查询性能
最容易检测到查询性能是否正常的指标就是查询本身。由查询引起的问题可能会导致时间太长而无法识别所需数据或返回数据。所以不妨在查询中排查以下问题。
1 选择过多冗余数据
编写查询语句来返回适当的数据是远远不够的,很可能你的查询语句会返回太多列,从而导致选择行和检索数据变得异常缓慢。所以,最好是列出所需的列,而不是直接用 SELECT。当需要在特定字段中查询时,该计划可能会确定一个覆盖索引从而加快结果返回。覆盖索引通常会包含查询中使用的所有字段。这意味着数据库可以仅从索引中产生结果,而不需要通过底层表来构建。
另外,列出结果中所需的列不仅可以减少传输的数据,还能进一步提高性能。
2 表之间的低效联接
联接会导致数据库将多组数据带到内存中进行比较,这会产生多个数据库读取和大量 CPU。根据表的索引,联接还可能需要扫描两个表的所有行。如果写不好两个大型表之间的联接,就需要对每个表进行完整扫描,这样的计算量将会非常大。其他会拖慢联接的因素包括联接列之间存在不同的数据类型、需要转换或加入包含 LIKE 的条件,这样就会阻止使用索引。另外,还需注意避免使用全外联接;在恰当的时候使用内部联接只返回所需数据。
3 索引过多或过少
如果查询优化没有可用的索引时,数据库会重新扫描表来产生查询结果,这个过程会生成大量的磁盘输入/输出(I/O)。适当的索引可以减少排序结果的需要。虽然非唯一值的索引在生成结果时,不能像唯一索引那样方便。如果键越大,索引也会变大,并通过它们创建更多的磁盘 I/O。大多数索引是为了提高数据检索的性能,但也需要明白索引本身也会影响数据的插入和更新,因为所有相关联的指标都必须更新。
4 太多的SQL导致争用解析资源
任何 SQL 查询在执行之前都必须被解析,在生成执行计划之前需要对语法和权限进行检查。由于解析非常耗时,数据库会保存已解析的 SQL 来重复利用,从而减少解析的耗时。因为 WHERE 语句不同,所以使用文本值的查询语句不能被共享。这将导致每个查询都会被解析并添加到共享池中,由于池的空间有限,一些已保存的查询会被舍弃。当这些查询再次出现时,则需要重新解析。
用户和查询冲突
数据库支持多用户,但多用户活动也可能造成冲突。
1 由慢查询导致的页/行锁定
为了确保查询产生精确的结果,数据库必须锁定表以防止在运行读取查询时再发生其他的插入和更新行为。如果报告或查询相当缓慢,需要修改值的用户可能需要等待至更新完成。锁提示能帮助数据库使用最小破坏性的锁。从事务数据库中分离报表也是一种可靠的解决方法。
2 事务锁和死锁
当两个事务被阻塞时会出现死锁,因为每一个都需要使用被另一个占用的资源。当出现一个普通锁时,事务会被阻塞直到资源被释放。但却没有解决死锁的方案。数据库会监控死锁并选择终止其中一个事务,释放资源并允许该事务继续进行,而另一个事务则回滚。
3 批处理 *** 作造成资源争夺
批处理过程通常会执行批量 *** 作,如大量的数据加载或生成复杂的分析报告。这些 *** 作是资源密集型的,但可能影响在线用户的访问应用的性能。针对此问题最好的解决办法是确保批处理在系统使用率较低时运行,比如晚上,或用单独的数据库进行事务处理和分析报告。
容量
并不是所有的数据库性能问题都是数据库问题。有些问题也是硬件不合适造成的。
1 CPU 不足或 CPU 速度太慢
更多 CPU 可以分担服务器负载,进一步提高性能。数据库的性能不仅是数据库的原因,还受到服务器上运行其他进程的影响。因此,对数据库负载及使用进行审查也是必不可少的。由于 CPU 的利用率时时在变,在低使用率、平均使用率和峰值使用率的时间段分别检查该指标可以更好地评估增加额外的 CPU 资源是否有益。
2 IOPS 不足的慢磁盘
磁盘性能通常以每秒输入/输出 *** 作(IOPS)来计。结合 I/O 大小,该指标可以衡量每秒的磁盘吞吐量是多少兆。同时,吞吐量也受磁盘的延迟影响,比如需要多久才能完成请求,这些指标主要是针对磁盘存储技术而言。传统的硬盘驱动器(HDD)有一个旋转磁盘,通常比固态硬盘(SSD)或闪存更慢。直到近期,SSD 虽然仍比 HDD 贵,但成本已经降了下来,所以在市场上也更具竞争力。
3 全部或错误配置的磁盘
众所周知,数据库会被大量磁盘访问,所以不正确配置的磁盘可能带来严重的性能缺陷。磁盘应该适当分区,将系统数据目录和用户数据日志分开。高度活跃的表应该区分以避免争用,通过在不同磁盘上存放数据库和索引增加并行放置,但不要将 *** 作系统和数据库交换空间放置在同一磁盘上。
4 内存不足
有限或不恰当的物理内存分配会影响数据库性能。通常我们认为可用的内存更多,性能就越好。监控分页和交换,在多个非繁忙磁盘中建立多页面空间,进一步确保分页空间分配足够满足数据库要求;每个数据库供应商也可以在这个问题上提供指导。
5 网速慢
网络速度会影响到如何快速检索数据并返回给终端用户或调用过程。使用宽带连接到远程数据库。在某些情况下,选择 TCP/IP 协议而不是命名管道可显著提高数据库性能。
配置
每个数据库都需设置大量的配置项。通常情况下,默认值可能不足以满足数据库所需的性能。所以,检查所有的参数设置,包括以下问题。
1 缓冲区缓存太小
通过将数据存储在内核内存,缓冲区缓存可以进一步提高性能同时减少磁盘 I/O。当缓存太小时,缓存中的数据会更频繁地刷新。如果它再次被请求,就必须从磁盘重读。除了磁盘读取缓慢之外,还给 I/O 设备增添了负担从而成为瓶颈。除了给缓冲区缓存分配足够的空间,调优 SQL 查询可以帮助其更有效地利用缓冲区缓存。
2 没有查询缓存
查询缓存会存储数据库查询和结果集。当执行相同的查询时,数据会在缓存中被迅速检索,而不需要再次执行查询。数据会更新失效结果,所以查询缓存是唯一有效的静态数据。但在某些情况下,查询缓存却可能成为性能瓶颈。比如当锁定为更新时,巨大的缓存可能导致争用冲突。
3 磁盘上临时表创建导致的 I/O 争用
在执行特定的查询 *** 作时,数据库需要创建临时表,如执行一个 GROUP BY 子句。如果可能,在内存中创建临时表。但是,在某些情况下,在内存中创建临时表并不可行,比如当数据包含 BLOB 或 TEXT 对象时。在这些情况下,会在磁盘上创建临时表。大量的磁盘 I / O 都需要创建临时表、填充记录、从表中选择所需数据并在查询完成后舍弃。为了避免影响性能,临时数据库应该从主数据库中分离出来。重写查询还可以通过创建派生表来减少对临时表的需求。使用派生表直接从另一个 SELECT 语句的结果中选择,允许将数据加到内存中而不是当前磁盘上。
NoSQL 数据库
NoSQL 的优势在于它处理大数据的能力非常迅速。但是在实际使用中,也应该综合参考 NoSQL 的缺点,从而决定是否适合你的用例场景。这就是为什么NoSQL通常被理解为 「不仅仅是 SQL」,说明了 NoSQL 并不总是正确的解决方案,也没必要完全取代 SQL,以下分别列举出五大主要原因。
1 挑剔事务
难以保持 NoSQL 条目的一致性。当访问结构化数据时,它并不能完全确保同一时间对不同表的更改都生效。如果某个过程发生崩溃,表可能会不一致。一致事务的典型代表是复式记账法。相应的信贷必须平衡每个借方,反之亦然。如果双方数据不一致则不能输入。NoSQL 则可能无法保证「收支平衡」。
2 复杂数据库
NoSQL 的支持者往往以高效代码、简单性和 NoSQL 的速度为傲。当数据库任务很简单时,所有这些因素都是优势。但当数据库变得复杂,NoSQL 会开始分解。此时,SQL 则比 NoSQL 更好地处理复杂需求,因为 SQL 已经成熟,有符合行业标准的接口。而每个 NoSQL 设置都有一个唯一的接口。
3 一致联接
当执行 SQL 的联接时,由于系统必须从不同的表中提取数据进行键对齐,所以有一个巨大的开销。而 NoSQL 似乎是一个空想,因为缺乏联接功能。所有的数据都在同一个表的一个地方。当检索数据时,它会同时提取所有的键值对。问题在于这会创建同一数据的多个副本。这些副本也必须更新,而这种情况下,NoSQL 没有功能来确保更新。
4 Schema设计的灵活性
由于 NoSQL 不需要 schema,所以在某些情况下也是独一无二的。在以前的数据库模型中,程序员必须考虑所有需要的列能够扩展,能够适应每行的数据条目。在 NoSQL 下,条目可以有多种字符串或者完全没有。这种灵活性允许程序员迅速增加数据。但是,也可能存在问题,比如当有多个团体在同一项目上工作时,或者新的开发团队接手一个项目时。开发人员能够自由地修改数据库,也可能会不断实现各种各样的密钥对。
5 资源密集型
NoSQL 数据库通常比关系数据库更加资源密集。他们需要更多的 CPU 储备和 RAM 分配。出于这个原因,大多数共享主机公司都不提供 NoSQL。你必须注册一个 VPS 或运行自己的专用服务器。另一方面,SQL 主要是在服务器上运行。初期的工作都很顺利,但随着数据库需求的增加,硬件必须扩大。单个大型服务器比多个小型服务器昂贵得多,价格呈指数增长。所以在这种企业计算场景下,使用 NoSQL 更为划算,例如那些由谷歌和 Facebook 使用的服务器。
1、查询SQL中的所有表: Select TABLE_NAME FROM 数据库名称INFORMATION_SCHEMATABLES Where TABLE_TYPE='BASE TABLE' 执行之后,就可以看到数据库中所有属于自己建的表的名称 2、查询SQL中所有表及列: Select dbosysobjectsname as Table_name, dbosyscolumnsname AS Column_name FROM dbosyscolumns INNER JOIN dbosysobjects ON dbosyscolumnsid = dbosysobjectsid Where (dbosysobjectsxtype = 'u') AND (NOT (dbosysobjectsname LIKE 'dtproperties')) 3、在Sql查询分析器,还有一个简单的查询方法: EXEC sp_MSforeachtable @command1="sp_spaceused ''" 执行完之后,就可以看到数据库中所有用户表的信息 4、查询总存储过程数:select count() 总存储过程数 from sysobjects where xtype='p' 附:xtype类型D = 默认值或 DEFAULT 约束
F = FOREIGN KEY 约束L = 日志FN = 标量函数
IF = 内嵌表函数
P = 存储过程
PK = PRIMARY KEY 约束(类型是 K)
RF = 复制筛选存储过程S = 系统表TF = 表函数
TR = 触发器U = 用户表UQ = UNIQUE 约束(类型是 K)V = 视图X = 扩展存储过程 另:在sqlserver中取得某个数据库中所有表名的sql语句 select sysobjectsname from sysobjectsxtype ='U';SELECT name
WHERE (xtype = 'U') 在数据库的sysobjects表里有这个数据库全部表的信息, xtype值为'U'的就是表名 注意:一般通过上述方法获得全部用户表示都会有一个dtproperties表,SQLSERVER 默认它也是用户表,想要从用户表中排出,需要加上限定条件 status>0,即:select from sysobjects where xtype='U' and status>0
本文首先讨论了基于第三范式的数据库表的基本设计,着重论述了建立主键和索引的策略和方案,然后从数据库表的扩展设计和库表对象的放置等角度概述了数据库管理系统的优化方案。
关键词: 优化(Optimizing) 第三范式(3NF) 冗余数据(Redundant Data) 索引(Index) 数据分割(Data Partitioning) 对象放置(Object Placement)
1 引言
数据库优化的目标无非是避免磁盘I/O瓶颈、减少CPU利用率和减少资源竞争。为了便于读者阅读和理解,笔者参阅了Sybase、Informix和Oracle等大型数据库系统参考资料,基于多年的工程实践经验,从基本表设计、扩展设计和数据库表对象放置等角度进行讨论,着重讨论了如何避免磁盘I/O瓶颈和减少资源竞争,相信读者会一目了然。
2 基于第三范式的基本表设计
在基于表驱动的信息管理系统(MIS)中,基本表的设计规范是第三范式(3NF)。第三范式的基本特征是非主键属性只依赖于主键属性。基于第三范式的数据库表设计具有很多优点:一是消除了冗余数据,节省了磁盘存储空间;二是有良好的数据完整性限制,即基于主外键的参照完整限制和基于主键的实体完整性限制,这使得数据容易维护,也容易移植和更新;三是数据的可逆性好,在做连接(Join)查询或者合并表时不遗漏、也不重复;四是因消除了冗余数据(冗余列),在查询(Select)时每个数据页存的数据行就多,这样就有效地减少了逻辑I/O,每个Cash存的页面就多,也减少物理I/O;五是对大多数事务(Transaction)而言,运行性能好;六是物理设计(Physical Design)的机动性较大,能满足日益增长的用户需求。
在基本表设计中,表的主键、外键、索引设计占有非常重要的地位,但系统设计人员往往只注重于满足用户要求,而没有从系统优化的高度来认识和重视它们。实际上,它们与系统的运行性能密切相关。现在从系统数据库优化角度讨论这些基本概念及其重要意义:
(1)主键(Primary Key):主键被用于复杂的SQL语句时,频繁地在数据访问中被用到。一个表只有一个主键。主键应该有固定值(不能为Null或缺省值,要有相对稳定性),不含代码信息,易访问。把常用(众所周知)的列作为主键才有意义。短主键最佳(小于25bytes),主键的长短影响索引的大小,索引的大小影响索引页的大小,从而影响磁盘I/O。主键分为自然主键和人为主键。自然主键由实体的属性构成,自然主键可以是复合性的,在形成复合主键时,主键列不能太多,复合主键使得Join作复杂化、也增加了外键表的大小。人为主键是,在没有合适的自然属性键、或自然属性复杂或灵敏度高时,人为形成的。人为主键一般是整型值(满足最小化要求),没有实际意义,也略微增加了表的大小;但减少了把它作为外键的表的大小。
(2)外键(Foreign Key):外键的作用是建立关系型数据库中表之间的关系(参照完整性),主键只能从独立的实体迁移到非独立的实体,成为后者的一个属性,被称为外键。
(3)索引(Index):利用索引优化系统性能是显而易见的,对所有常用于查询中的Where子句的列和所有用于排序的列创建索引,可以避免整表扫描或访问,在不改变表的物理结构的情况下,直接访问特定的数据列,这样减少数据存取时间;利用索引可以优化或排除耗时的分类作;把数据分散到不同的页面上,就分散了插入的数据;主键自动建立了唯一索引,因此唯一索引也能确保数据的唯一性(即实体完整性);索引码越小,定位就越直接;新建的索引效能最好,因此定期更新索引非常必要。索引也有代价:有空间开销,建立它也要花费时间,在进行Insert、Delete和Update作时,也有维护代价。索引有两种:聚族索引和非聚族索引。一个表只能有一个聚族索引,可有多个非聚族索引。使用聚族索引查询数据要比使用非聚族索引快。在建索引前,应利用数据库系统函数估算索引的大小。
① 聚族索引(Clustered Index):聚族索引的数据页按物理有序储存,占用空间小。选择策略是,被用于Where子句的列:包括范围查询、模糊查询或高度重复的列(连续磁盘扫描);被用于连接Join作的列;被用于Order by和Group by子句的列。聚族索引不利于插入作,另外没有必要用主键建聚族索引。
② 非聚族索引(Nonclustered Index):与聚族索引相比,占用空间大,而且效率低。选择策略是,被用于Where子句的列:包括范围查询、模糊查询(在没有聚族索引时)、主键或外键列、点(指针类)或小范围(返回的结果域小于整表数据的20%)查询;被用于连接Join作的列、主键列(范围查询);被用于Order by和Group by子句的列;需要被覆盖的列。对只读表建多个非聚族索引有利。索引也有其弊端,一是创建索引要耗费时间,二是索引要占有大量磁盘空间,三是增加了维护代价(在修改带索引的数据列时索引会减缓修改速度)。那么,在哪种情况下不建索引呢?对于小表(数据小于5页)、小到中表(不直接访问单行数据或结果集不用排序)、单值域(返回值密集)、索引列值太长(大于20bitys)、容易变化的列、高度重复的列、Null值列,对没有被用于Where子语句和Join查询的列都不能建索引。另外,对主要用于数据录入的,尽可能少建索引。当然,也要防止建立无效索引,当Where语句中多于5个条件时,维护索引的开销大于索引的效益,这时,建立临时表存储有关数据更有效。
批量导入数据时的注意事项:在实际应用中,大批量的计算(如电信话单计费)用C语言程序做,这种基于主外键关系数据计算而得的批量数据(文本文件),可利用系统的自身功能函数(如Sybase的BCP命令)快速批量导入,在导入数据库表时,可先删除相应库表的索引,这有利于加快导入速度,减少导入时间。在导入后再重建索引以便优化查询。
(4)锁:锁是并行处理的重要机制,能保持数据并发的一致性,即按事务进行处理;系统利用锁,保证数据完整性。因此,我们避免不了死锁,但在设计时可以充分考虑如何避免长事务,减少排它锁时间,减少在事务中与用户的交互,杜绝让用户控制事务的长短;要避免批量数据同时执行,尤其是耗时并用到相同的数据表。锁的征用:一个表同时只能有一个排它锁,一个用户用时,其它用户在等待。若用户数增加,则Server的性能下降,出现“假死”现象。如何避免死锁呢?从页级锁到行级锁,减少了锁征用;给小表增加无效记录,从页级锁到行级锁没有影响,若在同一页内竞争有影响,可选择合适的聚族索引把数据分配到不同的页面;创建冗余表;保持事务简短;同一批处理应该没有网络交互。
(5)查询优化规则:在访问数据库表的数据(Access Data)时,要尽可能避免排序(Sort)、连接(Join)和相关子查询作。经验告诉我们,在优化查询时,必须做到:
① 尽可能少的行;
② 避免排序或为尽可能少的行排序,若要做大量数据排序,最好将相关数据放在临时表中作;用简单的键(列)排序,如整型或短字符串排序;
③ 避免表内的相关子查询;
④ 避免在Where子句中使用复杂的表达式或非起始的子字符串、用长字符串连接;
⑤ 在Where子句中多使用“与”(And)连接,少使用“或”(Or)连接;
⑥ 利用临时数据库。在查询多表、有多个连接、查询复杂、数据要过滤时,可以建临时表(索引)以减少I/O。但缺点是增加了空间开销。
除非每个列都有索引支持,否则在有连接的查询时分别找出两个动态索引,放在工作表中重新排序。
3 基本表扩展设计
基于第三范式设计的库表虽然有其优越性(见本文第一部分),然而在实际应用中有时不利于系统运行性能的优化:如需要部分数据时而要扫描整表,许多过程同时竞争同一数据,反复用相同行计算相同的结果,过程从多表获取数据时引发大量的连接作,当数据来源于多表时的连接作;这都消耗了磁盘I/O和CPU时间。
尤其在遇到下列情形时,我们要对基本表进行扩展设计:许多过程要频繁访问一个表、子集数据访问、重复计算和冗余数据,有时用户要求一些过程优先或低的响应时间。
如何避免这些不利因素呢?根据访问的频繁程度对相关表进行分割处理、存储冗余数据、存储衍生列、合并相关表处理,这些都是克服这些不利因素和优化系统运行的有效途径。
31 分割表或储存冗余数据
分割表分为水平分割表和垂直分割表两种。分割表增加了维护数据完整性的代价。
水平分割表:一种是当多个过程频繁访问数据表的不同行时,水平分割表,并消除新表中的冗余数据列;若个别过程要访问整个数据,则要用连接作,这也无妨分割表;典型案例是电信话单按月分割存放。另一种是当主要过程要重复访问部分行时,最好将被重复访问的这些行单独形成子集表(冗余储存),这在不考虑磁盘空间开销时显得十分重要;但在分割表以后,增加了维护难度,要用触发器立即更新、或存储过程或应用代码批量更新,这也会增加额外的磁盘I/O开销。
垂直分割表(不破坏第三范式),一种是当多个过程频繁访问表的不同列时,可将表垂直分成几个表,减少磁盘I/O(每行的数据列少,每页存的数据行就多,相应占用的页就少),更新时不必考虑锁,没有冗余数据。缺点是要在插入或删除数据时要考虑数据的完整性,用存储过程维护。另一种是当主要过程反复访问部分列时,最好将这部分被频繁访问的列数据单独存为一个子集表(冗余储存),这在不考虑磁盘空间开销时显得十分重要;但这增加了重叠列的维护难度,要用触发器立即更新、或存储过程或应用代码批量更新,这也会增加额外的磁盘I/O开销。垂直分割表可以达到最大化利用Cache的目的。
总之,为主要过程分割表的方法适用于:各个过程需要表的不联结的子集,各个过程需要表的子集,访问频率高的主要过程不需要整表。在主要的、频繁访问的主表需要表的子集而其它主要频繁访问的过程需要整表时则产生冗余子集表。
注意,在分割表以后,要考虑重新建立索引。
32 存储衍生数据
对一些要做大量重复性计算的过程而言,若重复计算过程得到的结果相同(源列数据稳定,因此计算结果也不变),或计算牵扯多行数据需额外的磁盘I/O开销,或计算复杂需要大量的CPU时间,就考虑存储计算结果(冗余储存)。现予以分类说明:
若在一行内重复计算,就在表内增加列存储结果。但若参与计算的列被更新时,必须要用触发器更新这个新列。
若对表按类进行重复计算,就增加新表(一般而言,存放类和结果两列就可以了)存储相关结果。但若参与计算的列被更新时,就必须要用触发器立即更新、或存储过程或应用代码批量更新这个新表。
若对多行进行重复性计算(如排名次),就在表内增加列存储结果。但若参与计算的列被更新时,必须要用触发器或存储过程更新这个新列。
总之,存储冗余数据有利于加快访问速度;但违反了第三范式,这会增加维护数据完整性的代价,必须用触发器立即更新、或存储过程或应用代码批量更新,以维护数据的完整性。
33 消除昂贵结合
对于频繁同时访问多表的一些主要过程,考虑在主表内存储冗余数据,即存储冗余列或衍生列(它不依赖于主键),但破坏了第三范式,也增加了维护难度。在源表的相关列发生变化时,必须要用触发器或存储过程更新这个冗余列。当主要过程总同时访问两个表时可以合并表,这样可以减少磁盘I/O作,但破坏了第三范式,也增加了维护难度。对父子表和1:1关系表合并方法不同:合并父子表后,产生冗余表;合并1:1关系表后,在表内产生冗余数据。
4 数据库对象的放置策略
数据库对象的放置策略是均匀地把数据分布在系统的磁盘中,平衡I/O访问,避免I/O瓶颈。
⑴ 访问分散到不同的磁盘,即使用户数据尽可能跨越多个设备,多个I/O运转,避免I/O竞争,克服访问瓶颈;分别放置随机访问和连续访问数据。
⑵ 分离系统数据库I/O和应用数据库I/O。把系统审计表和临时库表放在不忙的磁盘上。
⑶ 把事务日志放在单独的磁盘上,减少磁盘I/O开销,这还有利于在障碍后恢复,提高了系统的安全性。
⑷ 把频繁访问的“活性”表放在不同的磁盘上;把频繁用的表、频繁做Join作的表分别放在单独的磁盘上,甚至把把频繁访问的表的字段放在不同的磁盘上,把访问分散到不同的磁盘上,避免I/O争夺;
⑸ 利用段分离频繁访问的表及其索引(非聚族的)、分离文本和图像数据。段的目的是平衡I/O,避免瓶颈,增加吞吐量,实现并行扫描,提高并发度,最大化磁盘的吞吐量。利用逻辑段功能,分别放置“活性”表及其非聚族索引以平衡I/O。当然最好利用系统的默认段。另外,利用段可以使备份和恢复数据更加灵活,使系统授权更加灵活。
通过sysbench的oltp_read_write测试来模拟业务压力、以此来给指定的硬件环境配置一份比较合理的MySQL配置文件。
环境介绍
硬件配置
软件环境
优化层级与指导思想
优化层级
MySQL数据库优化可以在多个不同的层级进行,常见的有:
SQL优化
参数优化
架构优化
本文重点关注:参数优化
指导思想
日志先行 -- 一个事务能否成功提交的关键是日志是否成功落盘,与数据没有太大的关系;也就是说对写的优化可以表述为各方面的资源向写 *** 作倾斜。
瓶颈分析 -- 通过show global status 的各个计数器的值基本上就能分析出当前瓶颈所在,再结合一些简单的系统层面的监控工具如top iostat 就能明确瓶颈。
整体性能是“读”&“写”之间的再平衡。
DB2数据库的性能与稳定性直接跟数据库对象的多少、大小有关。如果对象很少,不复杂,那么就算不怎么规划,也能够达到比较高的性能。如果对象数据比较多、比较大的话,那么就需要在数据库设计之前好好的规划,否则会在很大程度上影响数据库的性能与稳定性。
一、选择合适的语言与数据库字符集。
在企业中部署数据库的时候,首先需要在 *** 作系统上安装数据库。而在安装数据库的时候,需要选择安装的语言环境。即是以中文状态下安装数据库还是以英文状态安装数据库。如在启动安装程序的时,可以利用/i language选项来指定安装过程中所采用的语言。到目前为止,DB2数据库已经支持很多种语言。那么数据库在安装过程中,该采用什么语言呢?笔者建议,只要数据库管理员有一点英语基础,最好能够采用英文语言环境来进行安装。虽然说现在DB2数据库的中文语言环境已经设计的比较完善,但是笔者仍然担心其有一些不知名的漏洞。为此笔者在安装DB2数据库的时候,基本上都采用的是英文语言环境来进行安装。即将语言设置为“EN”,表示英文。提高DB2数据备份与恢复的效率。
另外如果DB2 数据库中要保存英文以外的数据,或者说用户会使用不同的字符集访问数据库时,还需要在数据库安装过程中选择特定的数据库字符集。DB2数据库中的所有字符数据,包括数据字典中的数据,都是存储在数据库字符集中的。如果用户使用不同的字符集访问数据库时,数据库管理员就需要选择包含所有这些用户的字符集的超集。只有如此,才能够确保系统能够很方便的使用替代字符完成字符的转换,从而提高数据库的性能。如果用户选择的字符集不对,有可能会出现一些莫名其妙的问题。如一次用户在安装数据库过程中,没有选择合适的字符集。虽然在使用的过程中,其存储中文字符没有问题。但是当对数据库采取还原 *** 作时,却发现还原后的数据库中有些原来是中文字符的地方,尽然出现了乱码。这主要就是没有选择合适的字符集惹的祸。有时候如果字符集选择不当的话,从外部数据源(如Excel表格)导入数据的时候,中文数据也会无法顺利导入。所以,数据库管理员在安装数据库的时候,需要根据实际企业,来选择合适的字符集。
二、评估数据库对象的大小、数量。
DB2数据库的性能与稳定性直接跟数据库对象的多少、大小有关。如果对象很少,不复杂,那么就算不怎么规划,也能够达到比较高的性能。如果对象数据比较多、比较大的话,那么就需要在数据库设计之前好好的规划,否则会在很大程度上影响数据库的性能与稳定性。其实DB2 数据库就好像一个仓库,数据库中的对象(如索引、数据表、表空间)等等就好像仓库中的货物。如果货物比较少,那么随便放放,仓库都显得很空旷。货物寻找起来也会很方便。但是如果货物数量比较多、比较大,就必须要对其存储空间进行合理规划。只有如此才能够让仓库的空间利用率达到最佳状态。并且货物的存放有序,在查找起来也特别的方便。笔者这里就以仓库管理为例,说话该如何做好数据库对象大小、数量等方便的评估,以及他们对于数据库性能与稳定性的影响。
1、根据对象大小来规划存储空间。在仓库货物的摆放上,要根据货物的大小来规划存储空间。或者说要首先防止大的货物。只有如此空间的利用率才会最高。其实在规划DB2对象的时候,也是如此。如某些表可能会包含的记录比较多,属于大表。此时数据库管理员就需要考虑,是否将其放置在一个独立的表空间或者硬盘空间上,以提高数据 *** 作的性能。大表所对应的索引往往也是比较大的。为此在硬件条件允许的情况下,将索引表与数据表分别存放在不同的硬盘上,可以提高数据库的性能。而对于一些比较小的对象(如数据表),可以将它们存放在一个表空间中。其实这个表空间就好像仓库中的一个个纸盒子。将小的对象放入到这个“纸盒子”中,不但不占空间,而且也容易管理。
2、根据对象的使用频率来规划存放空间。在仓库中摆放物品的时候,往往会把近期就要用到的货物或者频繁需要用到的东西放在仓库门口或者容易拿到的地方。如此在拿这些货物时就会比较便捷,也不会对其他货物产生影响。对于DB2数据库中的对象来说,也是这么一回事。可以将那些访问量比较大的对象,如索引、数据表,存放在性能比较好的硬盘上或者单独的硬盘中。此时访问这些数据,就不会与其它对象产生I/O冲突, *** 作起来速度就会比较快。而将不怎么用到的对象,存放在一起。由于他们不怎么被用到,所以即使存放在性能比较低的硬盘上,其对数据库性能产生的负面影响也是非常有限的。 在DB2数据库里面如何更新执行计划
3、根据类别来存放数据库对象。在仓库中存放货物的时候,还会对其进行分类。然后根据类别来进行存放。这有利于货物的管理与检索。其实在数据库对象存储空间设计时,也需要考虑这个因素。如现在应用软件在设计的时候,很多都是根据模块来设计。那么在数据库对象设计时,也需要根据这个模块来设计存储的空间。如将同一个模块的数据库对象存放在同一个表空间内。不过这可能会跟上面的两个建立相违背。此时最好是在对象的命名上做文章。如可以根据模块的不同,分别给数据库对象取一个相同的前缀或者后缀。如即使同一块模块要用到多个表空间,此时就可以给表空间一个相同的前缀。如此在管理数据库对象的时候,根据表空间的前缀就可以判断其所属的模块了。如果再加上一个后缀来表示其数据库对象的分类,那么就更合理了。为此在管理数据库对象的时候,要执行分类管理。不仅要从技术上对其进行分类,如分为索引、数据表、关键字等等。还需要从功能上进行分类,如按应用程序的模块来进行分类等等。
三、设计好数据库备份与还原的方案。
在数据库交付生产使用之后,往往需要进行大量的测试。但是在测试过程中往往又会产生很多的垃圾数据。可是交给企业应用的,肯定是一个干净的数据库系统。为此在数据库设计的时候,就需要想好如果减少测试过程中的垃圾数据。或者采取什么样的方式来实现在交互时自动清除垃圾数据的机制。
一般来说,想要一个数据库备份与还原的方案,减少数据库测试所产生的垃圾数据。如现在在给企业部署数据库的时候,往往是先安装一个干净的数据库系统。当然字符集这些需要预先设置好。然后再利用数据库还原功能将预先定义好的数据库模型还原出来。
另外有些时候需要两个方案互为补充。如在数据库初始化的过程中,采用数据库还原的方式来创建数据库对象。但是在应用软件升级的时候,由于此时已经有了用户的数据,为此不能够在使用数据库还原的方法。而是通过应用程序来执行某些SQL代码,来调整或者增加部分数据库对象。无论采用哪一种方式,需要遵循的一个原则就是在给企业创建数据库对象时要最大限度的减少测试。而要做到这一点,就是需要先在测试服务器上创建对象并测试对象可用。然后直接将相关的SQL代码在投入使用的数据库服务器上执行。
以上就是关于Hibernate性能调优全部的内容,包括:Hibernate性能调优、衡量数据库性能的重要指标、怎样查出SQLServer的性能瓶颈等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)