当索引的碎片过多时 会影响执行查询的速度 从而影响到我们的工作效率 这时候采取的最有利的措施莫过于重建索引了 本文主要介绍了Oracle数据库中检查索引碎片并重建索引的过程 接下来我们就开始介绍这一过程
重建索引的步骤如下
确认基本信息
登入数据库 找到专门存放index 的tablespace 并且这个tablespace下所有index的owner都是tax 将index专门存放在一个独立的tablespace 与数据表的tablespace分离 是常用的数据库设计方法
查找哪些index需要重建
通过anlyze index validate structure命令可以分析单个指定的index 并且将单个index 分析的结果存放到 index_stats试图下 一般判断的依据是
height > pct_used < % del_lf_rows / lf_rows + > g )
google上下载了遍历所有index脚本
发现anlyze index validate structure只能填充单个index分析信息 于是google了下 从网上下了个Loop 脚本 遍历索引空间下所有的索引名字 并且可以把所有index的分析信息存放到自己建立的一个用户表中
anlyze index 锁定index
发现下载的脚本不好用 应为anlyze index在分析索引前要争取独占锁 锁住index 很明显有些index正在被应用系统的使用 所以运行anlyze失败 这里吸取的教训是 尽量晚上做这种事 但是本人比较喜欢准时回家 所以在语句中添加Exception Handler 抛出anlyze index执行失败的那些index 名称 使脚本正常运行完毕 并且根据打印到前台的index name手动执行那些index分析
总结
虽然发现 个index中有 个符合上面的判断的依据 但是发现索引都不大 而那些拥有百万leaf的索引又没有符合上面的判断条件 所以结论是无需index rebuild online 没有啥碎片
什么时候可以rebuild index呢
rebuild index online 对那些有大量DML *** 作的大索引是有益的 可以每个月季度做一次针对较大索引的rebuild 通常哪怕rebuild index online也会造成I/O争用 所以有无online意义不大 可以放到 个晚上 分批执行rebuild index 锁定index 不让用户用(没有用户等入的时候) 并且加上paralle 关键字 应为发现数据库服务器有 个cpu processors
lishixinzhi/Article/program/Oracle/201311/19014
如何查看堆内内存的碎片情况 ?
glibc 提供了以下结构和接口来查看堆内内存和 mmap 的使用情况。
struct mallinfo {
int arena; / non-mmapped space allocated from system /
int ordblks; / number of free chunks /
int smblks; / number of fastbin blocks /
int hblks; / number of mmapped regions /
int hblkhd; / space in mmapped regions /
int usmblks; / maximum total allocated space /
int fsmblks; / space available in freed fastbin blocks /
int uordblks; / total allocated space /
int fordblks; / total free space /
int keepcost; / top-most, releasable (via malloc_trim) space /
};
/返回heap(main_arena)的内存使用情况,以 mallinfo 结构返回 /
struct mallinfo mallinfo();
/ 将heap和mmap的使用情况输出到stderr/
void malloc_stats();
可通过以下例子来验证mallinfo和malloc_stats输出结果。
#include <stdlibh>
#include <stdioh>
#include <stringh>
#include <unistdh>
#include <sys/mmanh>
#include <malloch>
size_t heap_malloc_total, heap_free_total,mmap_total, mmap_count;
void print_info()
{
struct mallinfo mi = mallinfo();
printf("count by itself:\n");
printf("\theap_malloc_total=%lu heap_free_total=%lu heap_in_use=%lu\n\tmmap_total=%lu mmap_count=%lu\n",
heap_malloc_total1024, heap_free_total1024, heap_malloc_total1024-heap_free_total1024,
mmap_total1024, mmap_count);
printf("count by mallinfo:\n");
printf("\theap_malloc_total=%lu heap_free_total=%lu heap_in_use=%lu\n\tmmap_total=%lu mmap_count=%lu\n",
miarena, mifordblks, miuordblks,
mihblkhd, mihblks);
printf("from malloc_stats:\n");
malloc_stats();
}
#define ARRAY_SIZE 200
int main(int argc, char argv)
{
char ptr_arr[ARRAY_SIZE];
int i;
for( i = 0; i < ARRAY_SIZE; i++)
{
ptr_arr[i] = malloc(i 1024);
if ( i < 128) //glibc默认128k以上使用mmap
{
heap_malloc_total += i;
}
else
{
mmap_total += i;
mmap_count++;
}
}
print_info();
for( i = 0; i < ARRAY_SIZE; i++)
{
if ( i % 2 == 0)
continue;
free(ptr_arr[i]);
if ( i < 128)
{
heap_free_total += i;
}
else
{
mmap_total -= i;
mmap_count--;
}
}
printf("\nafter free\n");
print_info();
return 1;
}
该例子第一个循环为指针数组每个成员分配索引位置 (KB) 大小的内存块,并通过 128 为分界分别对 heap 和 mmap 内存分配情况进行计数;
第二个循环是 free 索引下标为奇数的项,同时更新计数情况。通过程序的计数与mallinfo/malloc_stats 接口得到结果进行对比,并通过 print_info打印到终端。
下面是一个执行结果:
count by itself:
heap_malloc_total=8323072 heap_free_total=0 heap_in_use=8323072
mmap_total=12054528 mmap_count=72
count by mallinfo:
heap_malloc_total=8327168 heap_free_total=2032 heap_in_use=8325136
mmap_total=12238848 mmap_count=72
from malloc_stats:
Arena 0:
system bytes = 8327168
in use bytes = 8325136
Total (incl mmap):
system bytes = 20566016
in use bytes = 20563984
max mmap regions = 72
max mmap bytes = 12238848
after free
count by itself:
heap_malloc_total=8323072 heap_free_total=4194304 heap_in_use=4128768
mmap_total=6008832 mmap_count=36
count by mallinfo:
heap_malloc_total=8327168 heap_free_total=4197360 heap_in_use=4129808
mmap_total=6119424 mmap_count=36
from malloc_stats:
Arena 0:
system bytes = 8327168
in use bytes = 4129808
Total (incl mmap):
system bytes = 14446592
in use bytes = 10249232
max mmap regions = 72
max mmap bytes = 12238848
由上可知,程序统计和mallinfo 得到的信息基本吻合,其中 heap_free_total 表示堆内已释放的内存碎片总和。
如果想知道堆内究竟有多少碎片,可通过 mallinfo 结构中的 fsmblks 、smblks 、ordblks 值得到,这些值表示不同大小区间的碎片总个数,这些区间分别是 0~80 字节,80~512 字节,512~128k。如果 fsmblks 、 smblks 的值过大,那碎片问题可能比较严重了。
不过, mallinfo 结构有一个很致命的问题,就是其成员定义全部都是 int ,在 64 位环境中,其结构中的 uordblks/fordblks/arena/usmblks 很容易就会导致溢出,应该是历史遗留问题,使用时要注意!
一般索引碎片是由于
update/delete/insert *** 作,收缩文件,填充因子不合理,索引键设计不合理等造成的。
如果按照楼主说的,你可以定位一下究竟是什么原因造成的。系统是否频繁执行update/delete/insert *** 作,收缩文件之类的。另外索引的设计不合理这个也得重视。
本文需要你对索引和SQL中数据的存储方式有一定了解
在SQL Server中,存储数据的最小单位是页,每一页所能容纳的数据为8060字节而页的组织方式是通过B树结构(表上没有聚集索引则为堆结构,不在本文讨论之列)如下图:
在聚集索引B树中,只有叶子节点实际存储数据,而其他根节点和中间节点仅仅用于存放查找叶子节点的数据
每一个叶子节点为一页,每页是不可分割的 而SQL Server向每个页内存储数据的最小单位是表的行(Row)当叶子节点中新插入的行或更新的行使得叶子节点无法容纳当前更新或者插入的行时,分页就产生了在分页的过程中,就会产生碎片
理解外部碎片
首先,理解外部碎片的这个“外”是相对页面来说的。外部碎片指的是由于分页而产生的碎片比如,我想在现有的聚集索引中插入一行,这行正好导致现有的页空间无法满足容纳新的行。从而导致了分页:
因为在SQL SERVER中,新的页是随着数据的增长不断产生的,而聚集索引要求行之间连续,所以很多情况下分页后和原来的页在磁盘上并不连续
哈迪斯手稿索引怎么获得hades手稿怎么获得
hades手稿通过手稿碎片合成获得。因为hades手稿的获取方式是首先我们打开游戏,点击收集器,然后点击设收集手稿的碎片,点击合成就可以获得,所以hades手稿通过手稿碎片合成获得。
以上就是关于oracle数据库如何重建索引全部的内容,包括:oracle数据库如何重建索引、如何查看堆内内存的碎片情况、数据库索引重建之后,碎片率再次提高等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)