我开发一个Oracle数据库的应用程序,大约需要每秒5000次的数据访问,目前性能只能达到1000次,考虑使用内存缓存结果集的功能,但是期间遇到了一些问题,请教各位Oracle高手。环境是Oracle 10g
1、内存缓存应该是使用db_cache_size设置的,但是我们的Oracle是默认方式安装的,缓存好像是直接DBMS管理的,我用show parameter查看了下,结果是0,后来手动设置成了一个250M,不知道是否生效。
2、我们的运行环境是Linux,Oracle运行时总的占用6XXM内存,但是老是只有60M不到的实存,其实都在SWAP上面,如果db_cache缓存的内容不在内存中,那访问速度很难提上去,想请问下如何才能使这个db_cache始终驻留在内存而不被换到硬盘交换页上去呢?
3、是否是只要设置了缓存空间查询的数据就会缓存在内存中?还是说SQL语句中必需显式的指出需要缓存?
4、对缓存的使用有没有什么经验文档,请各位推荐下,多谢。

解决方案 »

  1.   

    缓存由两个参数控制SGA_TARGET和PGA_AGGREGATE_TARGET,设置了这两个参数,其他的基本内存部分都由Oracle自动配置为最优值,这也是Oracle推荐的方式。SGA_TARGET和PGA_AGGREGATE_TARGET是动态参数,可以在不重启数据库的情况下修改。但是SGA_TARGET受限于sga_max_size,SGA_TARGET不能超过sga_max_size,所以要增大sga_target先要增大sga_max_size,而sga_max_size是静态参数,修改sga_max_size必须重启Oracle。所以修改sga_target和pga_aggregate_target的过程如下:1、修改sga_max_sizeSQL>ALTER SYSTEM SET sga_max_size=4g scope=spfile;2、重启Oracle3、设置参数sga_target和pga_aggregate_target,   alter system set sga_target=4G;
       alter system set pga_aggregate_target=1g;
      

  2.   


    小小补充
    1. 你使用的是10g,已经是ASSM, oracle会根据统计的信息,自动的来调整你的内存组件的大小,你只需要设置sga_target即可。当然你可以手动设置db_cache_size,如果设置了的话,Oracle会在自动调整内存大小的时候把这个作为db_cache_size的最小值。对于sga_target,在动态修改的时候,最大值不能操过sga_max_size, 如果是 用scope=spfile这个方式来修改可以超过sga_max_size,应该此时sga_max_size也跟着变大了,如果超过的话。2.
    Oracle对数据库的cache有他自己的计算的,10g以后,内存是动态的根据对你使用系统的统计来进行调整的,如果出现问题,这块不是原因,你之所以db cache还没有上去,可能是访问的数据比较少,不过按3楼的,你加大db_cache_size的值,会保留这个内存空间的,但是也是一样的,数据load到内存里,才看得到变化。3.
    可以参考3lou4.
    每秒5000次的数据访问,是什么样的访问,你的系统是OLAP还是OLTP,这些应用上的东西对你的决定也有影响的,要谨记,数据库的优化和维护,不仅仅是DBA来做的。如果是到了只能通过DBA来做这一步的话,就相当于看病已经到了拿手术刀这一步了。 你的改变带来的风险和代价最高。
      

  3.   

    多谢3楼和4楼的答复,但是目前还有一个关键问题没有解决,就是作为cache的内存如何保证不换出到SWAP空间。回4楼,我的5000次访问都是数据查询,是对一个数据很大的单表查询,你说的OLAP还是OLTP是什么我不太懂,所以没法答。其实我也不能确定说数据访问慢是哪里的原因,当然首先怀疑磁盘IO的问题,想提升为cache访问。
      

  4.   

    要想减少磁盘读,只能增大内存的使用.楼主可以看看这个视图v$db_cache_size,并执行下面的查询:select block_size, size_for_estimate, size_factor, estd_physical_read_factor, estd_physical_reads from v$db_cache_advice;Oracle在这个视图中针对db_cache_size的大小会给出一些建议,楼主如果方便的话可以把结果贴出来看看.
      

  5.   


    解决get的IO的通常的办法就是物理上增加内存和逻辑上优化查询路径减少pg。你说的  就是作为cache的内存如何保证不换出到SWAP空间。只要你的内存足够的大,就不需要有这样的担心了。如果你是担心这个表被踢出内存了,你倒是可以把这个表pin到内存的keep pool里的。通过alter table tablename storage (buffer_pool keep) cache;不过对于这个个人觉得如果不是仔细的对系统进行分析而单独这样做,是没有什么意义的,对于一个经常访问的表来说,Oracle是会把他一直放到内存中的。
      

  6.   

    多谢各位指导,我明天把8楼说的查一下看。
    回9楼,我的内存不是足够大,我常查的表可能有200万条记录,约6XXM,但是我的db_cache_size只有2XXM。我是否应该考虑扩大SGA,然后再扩大db_cache_size。还该如3楼说的扩大SGA_MAX_SIZE和SGA_TARGET
      

  7.   


    如果内存不足够大的话,加大sga的负面影响就是你现在看到的swap过于频繁,页交换也是一个需要考虑的消耗。
      

  8.   

    按8楼的要求把这个打下来了,但是不太看得懂,请能看懂的给分析一下,多谢 
       BLOCK_SIZE SIZE_FOR_ESTIMATE SIZE_FACTOR ESTD_PHYSICAL_READ_FACTOR ESTD_PHYSICAL_READS
    1 8192 20 .0893 6.1454 270840
    2 8192 40 .1786 3.0632 135003
    3 8192 60 .2679 2.4908 109775
    4 8192 80 .3571 2.1411 94362
    5 8192 100 .4464 1.9619 86464
    6 8192 120 .5357 1.8235 80366
    7 8192 140 .625 1.6081 70873
    8 8192 160 .7143 1.5038 66275
    9 8192 180 .8036 1.3957 61510
    10 8192 200 .8929 1.1541 50861
    11 8192 220 .9821 1.0089 44465
    12 8192 224 1 1 44072
    13 8192 240 1.0714 .8524 37568
    14 8192 260 1.1607 .8184 36068
    15 8192 280 1.25 .7965 35103
    16 8192 300 1.3393 .793 34948
    17 8192 320 1.4286 .7908 34853
    18 8192 340 1.5179 .7905 34841
    19 8192 360 1.6071 .7905 34841
    20 8192 380 1.6964 .7905 34841
    21 8192 400 1.7857 .7873 34698我使用的Oracle主机参数是这样的:
    SGA_MAX_SIZE=580M
    SGA_TARGET=580M
    DB_CACHE_SIZE=200M
      

  9.   

    SIZE_FOR_ESTIMATE SIZE_FACTOR ESTD_PHYSICAL_READ_FACTOR ESTD_PHYSICAL_READS
    20 0.0893 6.1454 270840
    40 0.1786 3.0632 135003
    60 0.2679 2.4908 109775
    80 0.3571 2.1411 94362
    100 0.4464 1.9619 86464
    120 0.5357 1.8235 80366
    140 0.625 1.6081 70873
    160 0.7143 1.5038 66275
    180 0.8036 1.3957 61510
    200 0.8929 1.1541 50861
    220 0.9821 1.0089 44465
    224 1 1 44072
    240 1.0714 0.8524 37568
    260 1.1607 0.8184 36068
    280 1.25 0.7965 35103
    300 1.3393 0.793 34948
    320 1.4286 0.7908 34853
    340 1.5179 0.7905 34841
    360 1.6071 0.7905 34841
    380 1.6964 0.7905 34841
    400 1.7857 0.7873 34698首先感谢楼主的配合
    解释一下v$db_cache_advice的作用,Oracle利用这个视图对当前数据库db_cache_size大小提出一建议,提出了20个db_cache_size大小及相关的物理读的估计值,估计的db_cache_size大小的范围从当前的10%到200%,以10%为一个增加单位。
    下面解释几个列的含义
    size_for_estimate:估计的cache size大小
    size_factor:    估计的cache size大小与当前大小的比值
    estd_physical_reads:在估计的cache size大小情况下,会产生的物理读数量
    estd_physical_read_factor:估计的物理读数量与当前物理读数量的比值。从上面的数据中可以看到,当前db_cache_size为224M,其物理读为44072,增加cache size大小会减少物理读,当cache size到340M时,物理读的减少不再明显,因此db_cache_size大小为340M在目前情况下是一个合适的值。
    由于这里用的是自动共享内存管理方式,楼主应该增加sga_target,这样db_cache_size大小会相应增加,要增加sga_target要先增加sga_max_size。
      

  10.   

    考虑使用内存缓存结果集的功能,
    ===============================
    数据库会替你考虑的。连续访问的数据会自动缓存在db_cache中的缓存好像是直接DBMS管理的,
    ==========================
    对的我用show parameter查看了下,结果是0,
    ======================================
    不可能的只有60M不到的实存,其实都在SWAP上面
    =====================================
    系统其它服务占用了内存,或者你的数据库使用率不大,内存也被swap 出去了只要设置了缓存空间查询的数据就会缓存在内存中?
    ================================================
    所有的数据都必须缓存到内存中。
      

  11.   

    感谢楼上几位讲解,特别是13楼的zcs_1对缓存建议值的讲解很详细,分析也很到位。我在我的环境上做了个测试,发现固定查询一条数据(也就是说必在缓存中)性能也很低,只能达到2000次/秒的访问速度。也就是说应该还存在其它问题。我的测试机器是2个双核的1.4G的CPU,相当于1.4*4,内存是2G,SWAP也是2G,觉得性能不该这么低。我的程序是用OCI进行访问的,应用与Oralce同一个机器上跑,使用OCI的客户端,通过Net服务名联接数据库,保持长联系,每次查询使用句柄。
    查表的时候使用了索引,索引是对一个三个字段建议的,一个40字节的RAW和两个NUMBER字段,NUMBER字段都小于65535
    这样查询同一条记录,也只有2000CPS,请各位指点下可能是哪些方面的问题呢?
      

  12.   

    我觉得,数据库不是那种一个改一个参数就能,解决所的问题。
    如果是那样。 oracle  默认设个最优参数就行了。oracle 有自动内存管理了。
    访问速度上不去。
    你要查查应用程序逻辑是不是最优的。
    传进来的 sql 是不是全部绑定变量。
    是不是所有的索引都用上了。必要时让应用程序,采用第三方缓存。像memorycache.  很多php 程序把数据从mysql 读出来都缓存到 另一个内存很大的服务器上的一个内存数据库memorycache 中。 这样程序不用每次都去读数据库。梦想一个参数解决所有问题。不太现实。当然也可以考虑 dataguard .一个数据库写。多个备用库用来读。
      

  13.   

    各位高手,我想请教以下,我在自动建库的时候有几个参数需要设置,但是值我不知道怎么计算
    oracle11g版本sga_target=
    pga_aggregate_target=
    db_recovery_file_dest_size=
    open_cursons=
    processes=
    db_block_size=请指导以下参数的含义,再就是我该怎么设置这些值的大小呢?多谢