数据库缓存技术
数据缓存
(转自:http://www.cnblogs.com/sky20081816/archive/2012/03/26/2417996.html)
使用过Oracle数据库的人都知道,Oracle数据库的运行速度与效率,在同类数据库中是名列前茅的,特别是对大量数据进行访问时,更加有出色的表现。那么,Oracle数据库是靠什么实现的呢?笔者下面将通过一系列的文章,向大家展示Oracle数据库提供高性能运算的秘密。 Oracle数据库作为复杂运算的首选数据库,其首先是通过所谓的数据高速缓存来实现对数据的高速运算与操作的。 数据高速缓存跟操作系统的缓存类似,其存储最近从数据文件中读取的数据块,其中的数据可以被所有的用户所访问。如当我们利用Select语句从数据库中查询员工信息的时候,其首先不是从数据文件中去查询这个数据,而是从数据高速缓存中去查找,而没有这个必要再去查询磁盘中的数据文件了。只有在数据缓存中没有这个数据的时候,数据库才会从数据文件中去查询。Oracle数据库为什么要如此设计呢?这是由于数据库在读取数据的时候,读取内存的速度比读取磁盘的速度要快很多倍,所以这种机制可以提高数据的整体访问效率。 虽然其他数据库也有这方面的设计,但是,相对来说,Oracle数据库比其他数据库,在这方面有更加出色的表现。难怪Oracle数据库在内存的要求上,比其他数据库要高。若以稍微的代价牺牲一些内存,而换取更高的数据访问性能。笔者认为还是值得的。下面我们就来看看,Oracle数据库在数据高速缓存上有哪些特殊的表现。
一、 空闲缓存块。
当我们重新启动数据库后,系统就会为数据库分配一些空闲的缓存块。空闲缓存块中是没有任何数据的,他在那边默默的等着别写入记录。当Oracle 数据库从数据文件中读取数据后,数据库就会寻找是否有空闲的缓存块,以便将数据写入其中。
一般来说,数据库在启动的时候,就会在内存中预先分配这些缓存块。所以,Oracle数据库在启动的时候,会占用比较多的内存。但是,这可以免去在实际需要时向内存申请的时间。所以,有时候Oracle数据库虽然已启动,内存的占用率就很高,但是,其后续仍然可以正常运行的原因。而其他数据库虽然刚启动的时候内存占用率不是很高,但是,但系统内存到达80%以上时,在进行数据处理就会受到明显的影响。
所以,当我们利用SELECT语句从数据库文件中读取文件的时候,数据库首先会寻找是否有空闲的缓存。
二、 命中缓存块。
当SELECT语句先从数据库文件中读取数据后,会把取得的数据放入到这个命中缓存块中。也就是说,当我们利用查询语句从数据库查询处员工信息后,这个信息就会被保存在高速缓存中。直道高速缓存消耗完毕等原因,这个空间才会被释放。如此的话,下次用户在查询员工信息的时候,就不需要从数据库文件中再次查询相关信息,而直接从数据高速缓存中提取数据,从而提高数据库的访问效率。
另外要注意的一个问题是,命中缓存块中的数据不会被写入数据文件。确实,这个命中缓存块中的数据没有被更改,其当然也不会被写入数据库文件中。
三、脏缓存块。
当我们利用SELECT查询语句把员工信息的数据查询出来后,数据库会把这个数据所存储的空缓存块做标记,表示该缓存块已经存有数据,使命中缓存块。此时,我们若在利用数据更新语句UPDATE对其中某条记录进行更新时,如要把张三的名字改为张四。运行UPDATE语句后,数据库也首先从高速缓存中查找是否有这条记录,若存在这条记录的话,就直接更改这条记录,并且把该缓存块标记为赃缓存块。如此的话,就可以保持数据的一致性。
也就是说,脏缓存块存储的是已经被修改过的,但是还没有写入到数据库文件的信息。当SQL的UPDATE等数据更新语句对某个缓存块中的数据进行更改之后,这个命中缓存块就会被数据库标记为脏缓存块。当满足一定的条件时,这些脏缓存块中的数据内容会被写入到数据库文件中去,以便永久性的保留数据库修改记录。
当系统中没有空闲缓存块,而用户又需要查询数据时,数据库就查询当前所有的脏缓存块,把最先更改的脏缓存块中的内容先写入数据库文件中,以便释放这个脏缓存块。数据库就又会把这个脏缓存块标记为空闲缓存块,以方便用户下次存入数据。
Oracle数据库到底是通过什么手段,来控制空闲缓存块、命中缓存块、脏缓存块之间的相互转换的呢?说出来也许你不相信,Oracle数据库就是通过两张表,来管理这么复杂的功能。这两张表分别是DIRTY列表与LRU列表。
其中LRU列表保存着所有空闲缓存块、命中缓存块已经还没有被移入到DIRTY列表中的脏缓存块。
1、当用户查找员工信息时,数据库首先在LRU列表中查询是否有空闲缓存块。其查询的数据是从尾部开始查找。当查找有空闲的缓存块时,数据库就会把查到的数据写入到这个空闲缓存中。
2、若数据库在查询的时候,首先查到的是脏缓存的话,则会把这个脏缓存移动到DIRTY列表中,然后再继续查询,直到查询到合适的空闲缓存块为止。
3、若数据库在LRU列表中,从尾到头查了一遍,没有找到空闲缓存块,或者虽然有空闲缓存块,但是其容量不符合要求时,数据库就会暂时结束这一次查找。然后,系统就会触发数据库写进程,把DIRTY列表中的脏缓存块写入到数据库中去。已经被写入到数据库文件中去的脏缓存块将又被数据库标记为空闲缓存块,并插入到LRU列表中。当数据库执行完毕这个动作之后,数据库又会对LRU列表进行搜索,找到合适的数据高速空闲缓存之后,就会把读取的数据写入到这个空闲缓存中。所以,我们在利用数据库的时候,会发现有时候读取大量数据的时候,速度会比较慢。除了其他原因外,也有一部份原因是因为数据库没有查到足够大的空闲缓存在存放这些数据,故只好写进行读写操作,以释放更多的脏缓存,然后再进行查询操作。
1、为Oracle数据库配置尽量大的内存。Oracle数据库最新版本,根据官方的建议,其内存需要1G。虽然在低于这个内存数量的时候,数据库仍然可以运行,但是,其运行适度会大打折扣。当查询大量数据的时候,更是比较吃力。笔者现在使用的数据库服务器,是使用了4个G的内存。以前我用的是2个G 的。内存升级后,发现数据库的性能得到了比较大的改善。
2、在对数据进行查询操作时,尽量使用限制条件。如现在需要查询销售部门的员工信息时,我们不需要查询全部的员工信息,而是在SELECT语句中,利用WHERE条件语句设置查询条件。如此的话,就可以充分利用DIRTY列表中的空闲缓存块,而不会因为空闲缓存块容量不够而频繁的去执行数据库写操作。这会明显降低数据库的运行操作。同时,在查询时,最好也能够明确查询的信息,如你只需要员工的姓名与入职日期,那就不需要把员工的出生年月、身份证号码都查询出来。所以,有时候合理设计视图,也可以提高数据库的运行效率。
3、最好不要在数据库服务器上运行其他的服务。在数据库服务器中,若还运行其它服务器的话,除了硬件资源争夺影响服务器的运行效率之外,还会产生一个问题。就是会使得数据库的数据高速缓存块不连续。这会直接影响数据库查询空闲缓存块的效率。对脏缓存块进行数据库写入操作以及数据库进行标记之间的转换也会产生影响。所以,根据笔者的经验,数据库服务器最好能够独立。最多只能跟其对应的应用服务器部署在同一台服务器上。如现在Oracle数据库是一台 ERP系统的后台数据库,最好数据库能够跟ERP服务器分开部署。但是,若由于服务器资金的限制,那么可以把ERP应用服务器跟数据库服务器部署在一台服务器上。但是,不能再跟邮件服务器等应用服务器放在一起。这会影响数据高速缓存的管理效率,从而最终影响数据库的运行效能。现在服务器价格逐渐下滑,服务器的成本已经不是影响企业数据库应用的关键。所以,出于数据库性能考虑,笔者认为,企业在这上面还是应该大方的进行投资。没必要为了这么一点点钱,影响到数据库的性能。
查询语句缓存
MySQL数据库中缓存管理的思路解析
在数据库中,用户可能多次执行相同的查询语句。为了提高查询效率,数据库会在内存在划分一个专门的区域,用来存放用户最近执行的查询,这块区域就是缓存。因为内存的运行速度要比硬盘快的多。为此通过缓存机制,就可以提高查询的效率。当用户下一次再执行相同查询时,就可以直接从缓存中获取数据,而不用到硬盘中的数据文件中去读取数据,也可以省去相关解析的工作。
一、数据缓存的应用环境
并不是在任何情况下数据缓存都能够起到应有的效果。如果企业有一个不经常改变的表并且服务器受到这个表的大量的相同查询时,数据缓存才能够起到不错的效果。通常情况下,针对Web的应用,效果会比较明显。如现在在数据库中有一张产品信息表。企业的用户需要通过网页来查询产品的信息。如果在系统设计时,默认查询的结果是显示最近一个月交易过的产品信息。那么每次用户按默认情况查询产品信息时,将都会从缓存中获取信息(如果相关的信息没有被更新过)。此时系统查询的速度就会比较快。
如果企业有一个不经常改变的表并且服务器受到这个表的大量的相同查询时,笔者就建议大家启用数据缓存机制。在启动之前,可以先使用命名(如上图所示)来查询现在系统缓存是否开启。如上图所示,如果查询的结果是YES的话,那么就说明系统中已经开启了数据缓存机制。
二、数据缓存使用的限制
并不是在任何情况下,数据缓存都会起到改善查询的效果。根据笔者的项目经验,认为在一下几种情况,数据缓存机制的效果并不会很大。
一是查询所涉及到的表会经常更改。如在一个进销存管理系统中,可能会有产品与销售记录两张表格。产品表一般不怎么会更新,而销售记录表就可能每分钟都会发生变化。此时对于销售记录表来说,采用缓存机制就不会起到多大的效果。因为根据缓存的工作原理,当某个表被更改后,其对应的数据缓存的相关条目就会被清空。
二是查询缓存不使用与服务器方便些的语句。根据B/S或者C/S架构,可以将相关应用分为服务器断和客户端两类。在使用数据缓存时,数据库管理员要考虑到,在MySQL数据库中,查询缓存并不适用于服务器方所编写的查询语句。当数据库管理员正在使用服务器方编写的语句时,要注意到这些语句并不会应用缓存技术。
三是查询时使用缓存的两个基本条件:所采用的查询语句完全一样以及相关数据表妹欧发生更改。对于后面一条,上面已经谈到过。这里笔者要说的是,什么叫做查询语句瓦圈一样?简单的说,就是前后使用的两条查询语句(不一定要连在一起)完全一致。不仅包括查询的字段,也包括查询的条件。在这里要认识到一个误区。如果在5分钟之前用户查询一个产品信息表,其没有用到任何查询条件,查询全部的产品信息记录。5分钟之后又有一个用户查询产品信息表,此时其使用了查询条件,如只查询最近一个月新建的产品信息。显然此时后面一个查询的结果是前面一个查询结果的子集(不考虑产品基本表在这个时间间隔中是否做了更改)。照理来说应该可以使用数据缓存。但是这里需要注意,此时前后两条查询语句,其是不相同的(其查询条件不同)。即使结果是相同的,或者具有包含关系,数据库仍然会先重新解析SQL语句,然后从硬盘上的数据文件中去获取数据。
另外需要注意的是如果用户在查询语句中,使用了自定义函数、自定义变量或者因引用了系统数据库中的表,那么缓存机制也会失效。
三、提高缓存的使用效果
通过数据库的合理设计,可以提高缓存的使用效果,扩大缓存的使用领域。具体的说,数据库管理员可以从如下几个方面出发。
1、 根据数据变化的频率来分解表
如现在有产品基本资料与产品最新库存两部分内容。在不考虑缓存的情况下,可以将产品基本资料与产品库存放在同一个表中,然后通过其他作业来更新这个库存数量。如此的话,在前台界面中,就可以直观的反映出产品的库存数量。但是从缓存的设计角度来看,这么操作并不是很合理。因为产品信息相对来说不怎么会变化,而库存数量却经常在发生变化。如果将他们放在同一张表上,由于库存数量的不断更新,数据缓存中的内容就会不断被清空(与产品信息表相关的数据缓存)。此时如果很多用户要查询产品的描述、规格(他们可能并不关注产品的库存),那么他们就无法使用数据缓存。因为缓存中没有相关的数据(由于库存数量不断变化而被清空)。
遇到这种情况时,数据库管理员就可以将库存数量与产品基本信息存放在两张不同的表上,然后通过关键字来进行关联。这么做的好处就是库存数量更新并不会影响到产品基本信息表所对应的数据缓存(他们是两张表)。从而提高产品信息查询时的缓存命中率。
2、 采用默认条件的查询来提高缓存命中率
在上面的分析中笔者谈到,要两条完全相同的SQL语句才能够使用缓存。条件不同或者使用的字段不同,数据库系统都不会使用缓存来进行查询优化。另外MySQL数据库与其他数据库不一样,对于SQL语句解析来说,其大小写实敏感的。也就是说同一条查询语句,如果其关键字的大小写不同,那么也会被认为是用了不同的SQL语句。这一点是比较让人头疼的。针对这种情况,在客户端应用程序设计时,最好注意以下几点。
一是要习惯采用默认条件的查询来提高缓存命中率。如在设计产品信息查询这个功能,可以考虑默认查询全部信息或者指定某个固定的条件。如此就可以提高缓存的命中率。而不要在不同的用户界面设置不同的默认值。某些应用系统,为了提高界面的友好性,会给用户提供一些个性化设置的参数,以保存用户的个性化内容。此时虽然可以提高界面的人性化,但是显然会降低数据缓存的命中率。遇到这种情况时,数据库管理员就需要在人性化设计与系统的查询性能之间进行均衡。
不同的应用针对同一个表格的相同查询,其查询语句最好相同。如现在对于产品信息,即可以通过产品信息窗口进行查询,也可以根据报表来查询。此时其对应的后台表格是相同的。只要其执行的查询语句相同、并且在这段时间之内数据库表格没有发生变化,那么系统就可以从缓存中获取数据。在实际工作中,窗体与报表往往是有不同的人设计与开发的。如果现在这两个人SQL语句的书写习惯不同,一个人喜欢用大写,而另外一个人喜欢用小写。在系统中,对于SQL查询语句解析时区分大小写。如果大小写不同,则会被认为不同的SQL语句,此时系统也就无法使用缓存了。为此在遇到这种情况时,不同的用户之间要统一SQL语句的书写规范,如要么全部使用大写,要么全部使用小写。项目管理员要根据实际情况来制定相关的规则。
3、 提高缓存空间大小来提高数据库的缓存命中率
当数据缓存满时,新的数据会覆盖旧的数据。如现在用户查询了一笔产品信息。1个小时后其在利用相同的语句查询了这个产品信息(假设在这个过程中产品信息表没有发生变化)。查询语句是否会采用缓存呢?答案是不一定。如果企业服务器的缓存空间足够的大,旧的缓存信息没有被新的查询内容所覆盖,那么就会采用缓存中的信息。相反,如果缓存比较小,此时系统旧的缓存信息就会被新的查询内容所覆盖掉。在这种情况下,即使查询的语句相同、表格也没有发生变化,数据库系统仍然要从硬盘上的数据文件中去获取数据。
为此为了提高查询的效率,提高缓存的命中率,最好能够增加服务器上缓存的空间。现在内存价格比较便宜,这笔投资应该不会太大。特别是当在一台服务器上实现不同的应用时,提高内存的容量还是蛮有必要的。