分享
 
 
 

使用treemaps图形化表示数据库

王朝other·作者佚名  2008-05-31
窄屏简体版  字體: |||超大  

在一个 Oracle 数据库中,DBA 经常要寻找快要用完的表空间,然后要么增加一个新的数据文件,要么删除旧的数据,从而保证应用程序不至于出于因空间错误而失败。我想将treemaps应用到这个问题上可能非常有趣。

我发现到从一个数据库查询中产生一个图形图像在各种环境下有区别,因此我决定将这分两部分写这篇文章。

第一部分讨论使用 PHP 文件产生 PNG 图像;第二部分则分析使用modplsql从 PL/SQL 产生一个 SVG 格式的图像。大多数浏览器都支持 PNG 格式的图像文件,但是并不是每个人都安装了 PHP 服务器。然而将相同的代码应用到其它服务器上相当简单,比如说应用到 Java servlet上,Java servlet具有动态产生图像文件的能力。

有几种不同的算法可以用来产生treemap.我选择 pivot 算法,该算法能够避免一个常见的问题,即非常小的数据会挤到另外一个小区域内。

在这个例子中,我想要产生一个treemap,使用该treemap来包含一个矩形表示每一个表空间。每个矩形都用绿色、黄色和红色三种颜色不同的深浅度标出,并用此法显示在每个表空间中还有多少自由空间。绿色表空间表示有很多自由空间,黄色表空间表示自由空间还有一半,红色表空间表示已经几乎没有自由空间。在每个基本颜色之间我们使用不同的深浅度。(相比查看一大堆表空间大小和百分比来说这样可读性更好。)

数据和表现之间可能的结合有无数种。Treemaps非常擅长显示有很多条目的数据。对这个例子进行扩展,可以将每个矩形再分成小矩形,分别用来表示每个数据文件,相应地还可以继续再分成更小的矩形,分别用来表示已用的或自由的区域(extent)。我们还要编写一个小程序来显示 SGA 分配和使用统计情况。

为了生成用于产生图表的数据,我需要 DBA_DATA_FILES(里面有已分配的总空间数)和DBA_FREE_SPACE.我可以通过拿“总字节数”减去“已用字节数”来计算“自由字节数”,从而避免查询自由 extent 表。这个视图的 USER_ 和 ALL_ 版本不能查看到所有的数据,但是我不想将 DBA 权限给那些想得到这些数据的人。所以我拆开了 DNA_DATA_FILES 和 DBA_FREE_SPACE,从中先删除了不相关的表,然后将它们合并到了一个单独的视图中,使用该视图显示已用的空间(自由空间为“0”)和自由空间(已用空间为“0”)。这样就提高了查询速度,而且通过将这个视图授权给 PUBLIC,任何数据库用户都可以访问其数据。

下面是我的视图定义,数据库版本为 Oracle 9.2.0.1.0。

create or replace view treemap_data_view

as

selectts.nametablespace_name,

0 free_bytes,

ts.blocksize * f.blocksused_bytes,

ts.blocksize * f.blockstotal_bytes

fromsys.file$ f, sys.ts$ ts

where f.spare1 is null

andf.ts# = ts.ts#

union all

selectts.name,

0,

decode(hc.ktfbhccval,0,ts.blocksize * hc.ktfbhcsz,null),

decode(hc.ktfbhccval,0,ts.blocksize * hc.ktfbhcsz,null)

fromsys.ts$ ts, sys.x$ktfbhchc

wherehc.ktfbhctsn = ts.ts#

union all

selectts.name,

f.length * ts.blocksize,

0,

f.length * ts.blocksize

fromsys.ts$ ts, sys.fet$ f

wherets.ts# = f.ts#

andts.bitmapped = 0

union all

selectts.name,

f.ktfbfeblks * ts.blocksize,

0,

f.ktfbfeblks * ts.blocksize

fromsys.ts$ ts, sys.x$ktfbfe f

wherets.ts# = f.ktfbfetsn

andts.bitmapped <> 0 and ts.online$ in (1,4) and ts.contents$ = 0;

grant select on treemap_data_view to public;

剩下的工作就是用PHP 文件来产生图表。该文件接受宽度和长度参数来调整被约束的区域的大小。我为图像分配了一个颜色表,颜色0是背景色,颜色1是文本和边界颜色,颜色2-128是绿色和黄色之间的颜色,颜色129-256是黄色和红色之间的颜色。

函数gendate将数据从数据库装入到一个本地表中。函数ImageCenterString在矩形的中心画一些文本(表空间的名字)。

函数TreemapDrawGroup画treemap矩形,使用相应的颜色填充矩形,并在矩形上写名字。 TreemapGroup函数递归地将数据分成交互的垂直和水平分割,划分的依据是每一边的大小,即相对于表空间的大小的百分比。数据首先填入一个数组然后使用 PHP 函数“array_sum()”将两边相加得出总的大小。下面是 PHP 代码:

<?php

// send header

Header("Content-Type: image/png");

// look

$font = 4;

$fontwidth = ImageFontWidth($font);

$fontheight = ImageFontHeight($font);

// the query

$username = 'scott';

$passWord = 'tiger';

$sql = <<<SQL

selecttablespace_name,

sum(free_bytes),

sum(used_bytes),

sum(total_bytes)

fromtreemap_data_view

group by tablespace_name

SQL;

// where tablespace_name in ('SYSTEM','EJALA','TOOLS')

// generate treemap data

functiongendata()

{

global $username,$password,$sql;

// arrange this way to take advantage of "array_sum"

$tmdata = array

(

'name'=>array(),

'freebytes'=>array(),

'usedbytes'=>array(),

'totalbytes'=>array()

);

$conn = ora_logon($username,$password);

ora_commitoff($conn);

$cursor = ora_open($conn);

ora_parse($cursor,$sql);

ora_exec($cursor);

$i = 0;

while (ora_fetch($cursor))

{

$tmdata['name'][$i] = trim(ora_getcolumn($cursor,0));

$tmdata['freebytes'][$i] = ora_getcolumn($cursor,1);

$tmdata['usedbytes'][$i] = ora_getcolumn($cursor,2);

$tmdata['totalbytes'][$i] = ora_getcolumn($cursor,3);

$i++;

}

ora_close($cursor);

ora_logoff($conn);

return $tmdata;

}

// draw text centered in a rectangle

functionImageCenterString(&$image,$x,$y,$wd,$ht,$string)

{

global $font,$fontwidth,$fontheight;

$tw = $fontwidth * strlen($string);

$cx = ($tw > $wd) ?0 : ($wd - $tw) >> 1;

$cy = ($fontheight > $ht) ?0 : ($ht - $fontheight) >> 1;

ImageString($image,$font,$x+$cx,$y+$cy,$string,1);

}

functionTreemapDrawGroup(&$image,$x,$y,$wd,$ht,&$tmdata,$i)

{

$pctfree = $tmdata['freebytes'][$i]/$tmdata['totalbytes'][$i];

$color = round($pctfree * 254) + 2.0;

ImageFilledRectangle($image,$x+1,$y+1,$x+$wd-1,$y+$ht-1,$color);

ImageCenterString($image,$x,$y,$wd,$ht,$tmdata['name'][$i]);

}

functionTreemapGroup($lvl,&$image,$x,$y,$wd,$ht,&$tmdata)

{

$cnt = count($tmdata['name']);

switch ($cnt)

{

case 1:

// use entire area for rectangle

TreemapDrawGroup($image,$x,$y,$wd,$ht,$tmdata,0);

break;

case 2:

// draw split region

$pct = $tmdata['totalbytes'][0]

/ ($tmdata['totalbytes'][0] + $tmdata['totalbytes'][1]);

if ($lvl % 2)

{

// odd = vertical split

$ht1 = $ht * $pct;

TreemapDrawGroup($image,$x,$y,$wd,$ht1,$tmdata,0);

ImageLine($image,$x,$y+$ht1,$x+$wd,$y+$ht1,1);

TreemapDrawGroup($image,$x,$y+$ht1,$wd,$ht-$ht1,$tmdata,1);

}

else {

/// even = horizontal split

$wd1 = $wd * $pct;

TreemapDrawGroup($image,$x,$y,$wd1,$ht,$tmdata,0);

ImageLine($image,$x+$wd1,$y,$x+$wd1,$y+$ht,1);

TreemapDrawGroup($image,$x+$wd1,$y,$wd-$wd1,$ht,$tmdata,1);

}

break;

default:

// recursively pivot slices

$s = $cnt >> 1; // determine split point

$tm1 = array

(

'name' => array_slice($tmdata['name'],0,$s),

'freebytes' => array_slice($tmdata['freebytes'],0,$s),

'usedbytes' => array_slice($tmdata['usedbytes'],0,$s),

'totalbytes' => array_slice($tmdata['totalbytes'],0,$s)

);

$tm2 = array

(

'name' => array_slice($tmdata['name'],$s),

'freebytes' => array_slice($tmdata['freebytes'],$s),

'usedbytes' => array_slice($tmdata['usedbytes'],$s),

'totalbytes' => array_slice($tmdata['totalbytes'],$s)

);

$tm1sum = (float)array_sum($tm1['totalbytes']);

$tm2sum = (float)array_sum($tm2['totalbytes']);

$pct = $tm1sum / ($tm1sum + $tm2sum);

if ($lvl % 2)

{

// odd = vertical split

$ht1 = $ht * $pct;

TreemapGroup($lvl+1,$image,$x,$y,$wd,$ht1,$tm1);

ImageLine($image,$x,$y+$ht1,$x+$wd,$y+$ht1,1);

TreemapGroup($lvl+1,$image,$x,$y+$ht1,$wd,$ht-$ht1,$tm2);

} else {

// even = horizontal split

$wd1 = $wd * $pct;

TreemapGroup($lvl+1,$image,$x,$y,$wd1,$ht,$tm1);

ImageLine($image,$x+$wd1,$y,$x+$wd1,$y+$ht,1);

TreemapGroup($lvl+1,$image,$x+$wd1,$y,$wd-$wd1,$ht,$tm2);

}

break;

}

}

// create image and colors

$wd = ($_REQUEST["width"]) ? $_REQUEST["width"] : 640;

$ht = ($_REQUEST["height"]) ? $_REQUEST["height"] : 480;

$im = ImageCreate($wd,$ht);

// allocate colors

ImageColorAllocate($im,255,255,255); // background = white

ImageColorAllocate($im,0,0,0); // text = black

// allocates 254 shades from green -> yello -> red

for ($i=0;$i<126;$i++) { ImageColorAllocate($im,$i*2,255,0); }

for ($i=0;$i<126;$i++) { ImageColorAllocate($im,255,255-($i*2),0); }

$tmdata = gendata();

TreemapGroup(0,$im,0,0,$wd,$ht,$tmdata);

// ImageCenterString($im,0,0,$wd,$ht,"count = ".count($tmdata['name']));

// draw border at edges of image

ImageLine($im,0,0,0,$ht-1,1);

ImageLine($im,0,$ht-1,$wd-1,$ht-1,1);

ImageLine($im,$wd-1,$ht-1,$wd-1,0,1);

ImageLine($im,$wd-1,0,0,0,1);

// generate image to output

ImagePNG($im);

ImageDestroy($im);

?>

本文作者:Scott Stephens已经在Oracle工作了13年有余,他曾经在技术支持、电子商务、市场和软件开发等部门工作。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有