搜尋
首頁php教程php手册改进的PHP文本数据库类

数据|数据库

找了些时间,改进了自己文本数据库系统,从空间利用效率和并发性能两个方面着手,搞高了程序性能。

在空间利用率上,做了两点改进,一是在删除记录的时候,如果记录的存放位置在数据库的末端,就自动修改数据库末端指针,而不是将此记录的空间作为一个闲置块存入闲置块记录中,这样就可以继续在数据文件尾分配任意长度的空间而不是像以前那样将这个删除记录的空间整块分配给下一次请求空间的新记录;第二点改进是在从闲置块中请求空间的时候,不仅继续采用原来的最佳适应法,而且在请求到合适的闲置块的时候并不是将整个块而是将其部分划分给新记录,这样又进一部提高了空间的利用率。

在并发性能上,增加了数据库的打开模式这个选项。为了保持文本数据库操作的原子性,以前都以写模式打开数据库,用户无论是从数据库中读数据或写数据,系统都会锁定数据库而禁止其它用户并发的读写操作,而大多情况下,用户都是浏览网页而不是POST数据,禁止对数据库的并行的读操作,势必成为网页浏览速度的瓶颈,为了加速网页生成速度,在数据库中加入了打开模式这一选项,在只读模式下,可以允许不同的用户并发地从数据库中申请数据,使得网页并发性能得到了一定程序上的提高。

下面给出新文本数据库类的部分代码,其相关注释可以从原来的文章:http://202.113.13.169/site/redboy/index.php?item=read&id=1&blogID=4中获得。

源代码:


class TxtDB
{
    var $name='';//文本数据库名
    var $path='';
    var $minLen=20;
    var $isError;
    var $dbh;
    var $indxh;
    var $lfth;
    var $lckh;
    var $rcdCnt=0;
    var $maxID=0;
    var $leftCnt=0;
    var $DBend=0;
    var $mod='w';

    function TxtDB($name,$mod='w',$path='bpns_dbm')
    {
        $this->name=$name;
        $this->path=$path.'/'.$name;
        $this->isError=0;
        $this->mod=$mod;
        $path=$this->path;
        if ($name!='')
        {
            @mkdir($this->path,0777);
            if (!file_exists($path.'/'.$name.'.tdb')) $this->dbh=fopen($this->path.'/'.$name.'.tdb','w+');
            else $this->dbh=fopen($path.'/'.$name.'.tdb','r+');
            if (!file_exists($path.'/'.$name.'.indx')) $this->indxh=fopen($this->path.'/'.$name.'.indx','w+');
            else $this->indxh=fopen($path.'/'.$name.'.indx','r+');
            if (!file_exists($path.'/'.$name.'.lft')) $this->lfth=fopen($this->path.'/'.$name.'.lft','w+');
            else $this->lfth=fopen($this->path.'/'.$name.'.lft','r+');
            if ($this->mod=='w')
            {
                 $this->lckh=fopen($this->path.'/'.$name.'.lck','w');
                 flock($this->lckh,2);
                 fwrite($this->lckh,'lck');//lock the datebase
            }
            $rcd=$this->getRcd(0);
            $this->rcdCnt=$rcd[id];
            $this->maxID=$rcd[loc];
            $this->DBend=$rcd[len];
            $rcd=$this->getLeft(0);
            $this->leftCnt=$rcd[loc];
        }
        else $this->isError=1;
    }

    function setRcd($rid,$id,$loc,$len)
    {
        fseek($this->indxh,$rid*12);
        $str=pack('III',$id,$loc,$len);
        fwrite($this->indxh,$str,12);
    }

    function getRcd($rid)
    {
        fseek($this->indxh,$rid*12);
        $str=fread($this->indxh,12);
        $rcd=array();
        $rcd[id]=str2int($str);
        $rcd[loc]=str2int(substr($str,4,4));
        $rcd[len]=str2int(substr($str,8,4));
        return $rcd;
    }

    function setLeft($lid,$loc,$len)
    {
        fseek($this->lfth,$lid*8);
        $str=pack('II',$loc,$len);
        fwrite($this->lfth,$str,8);
    }

    function getLeft($lid)
    {
        fseek($this->lfth,$lid*8);
        $str=fread($this->lfth,8);
        $rcd[loc]=str2int($str);
        $rcd[len]=str2int(substr($str,4,4));
        return $rcd;
    }

    function clear()
    {
        $this->setRcd(0,0,0,0);
        $this->setLeft(0,0,0);
    }

    function close()
    {
        @fclose($this->dbh);
        @fclose($this->indxh);
        @fclose($this->lfth);
        @fclose($this->lckh);
    }

    function seekSpace($len)
    {
        $res=array('loc'=>0,'len'=>0);
        if ($this->leftCnt        $find=0;
        $min=1000000;
        for ($i=$this->leftCnt;$i>0;$i--)
        {
            $res=$this->getLeft($i);
            if ($res[len]==$len) {$find=$i;break;}
            else if($res[len]>$len)
            {
                if ($res[len]-$len                {
                    $min=$res[len]-$len;
                    $find=$i;
                }
            }
        }
        if ($find)
        {
            $res=$this->getLeft($find);
            if ($res[len]            {
                fseek($this->lfth,($find+1)*8);
                $str=fread($this->lfth,($this->leftCnt-$find)*8);
                fseek($this->lfth,$find*8);
                fwrite($this->lfth,$str);
                $this->leftCnt--;
                $this->setLeft(0,$this->leftCnt,0);
                return $res;
            }
            else
            {
                $rs=array();
                $rs[loc]=$res[loc];
                $rs[len]=$len;
                $res[loc]+=$len;
                $this->setLeft($find,$res[loc],$res[len]-$len);
                return $rs;
            }
        }
        else//fail
        {
            $res[len]=0;
            return $res;
        }
    }

    function insert($content,$len=0)//return with record id
    {
        $res=array('loc'=>0);
        if ($this->mod!='w') return 0;
        if (!$len) $len=strlen($content); 
        if ($lenminLen) $len=$this->minLen;
        if ($this->leftCnt) $res=$this->seekSpace($len);
        if (!$res[len])
        {
            $res[loc]=$this->DBend;
            $res[len]=$len;
        }
        if ($res[loc]+$res[len]>$this->DBend) $this->DBend=$res[loc]+$res[len];
        //echo $this->DBend.'
';
        $this->maxID++;
        $this->rcdCnt++;
        $this->setRcd(0,$this->rcdCnt,$this->maxID,$this->DBend);
        $this->setRcd($this->rcdCnt,$this->maxID,$res[loc],$res[len]);
        fseek($this->dbh,$res[loc]);
        fwrite($this->dbh,$content,$len);
        return $this->maxID;
    }

    function findByID($id)
    {
        if ($id$this->maxID or $this->rcdCnt        $left=1;
        $right=$this->rcdCnt;
        while($left        {
            $mid=(int)(($left+$right)/2);
            if ($mid==$left or $mid==$right) break;
            $rcd=$this->getRcd($mid);
            if ($rcd[id]==$id) return $mid;
            else if($id            else $left=$mid;
        }
        //$rcd=$this->getRcd($mid);
        //if ($rcd[id]==$id) return $mid;
        $rcd=$this->getRcd($left);
        if ($rcd[id]==$id) return $left;
        $rcd=$this->getRcd($right);
        if ($rcd[id]==$id) return $right;
        return 0;
    }

    function delete($id)
    {
        if ($this->mod!='w') return 0;
        $rid=$this->findByID($id);
        if (!$rid) return;
        $res=$this->getRcd($rid);
        fseek($this->indxh,($rid+1)*12);
        $str=fread($this->indxh,($this->rcdCnt-$i)*12);
        fseek($this->indxh,$rid*12);
        fwrite($this->indxh,$str);
        $this->rcdCnt--;
        if ($res[loc]+$res[len]==$this->DBend)
        {
            $this->DBend=$res[loc];
            $this->setRcd(0,$this->rcdCnt,$this->maxID,$this->DBend);
        }
        else
        {
            $this->setRcd(0,$this->rcdCnt,$this->maxID,$this->DBend);
            $this->leftCnt++;
            $this->setLeft(0,$this->leftCnt,0);
            $this->setLeft($this->leftCnt,$res[loc],$res[len]);
        }
    }

    function update($id,$newcontent,$len=0)
    {
        if ($this->mod!='w') return;
        $rid=$this->findByID($id);
        if (!$rid) return;
        if (!$len) $len=strlen($newcontent); 
        $rcd=$this->getRcd($rid);
        if ($rcd[len]        {
            $this->leftCnt++;
            $this->setLeft(0,$this->leftCnt,0);
            $this->setLeft($this->leftCnt,$rcd[loc],$rcd[len]);
            $rcd[loc]=$this->DBend;
            $rcd[len]=$len;
            $this->DBend+=$len;
            $this->setRcd(0,$this->rcdCnt,$this->maxID,$this->DBend);
            $this->setRcd($rid,$rcd[id],$rcd[loc],$rcd[len]);
        }
        fseek($this->dbh,$rcd[loc]);
        fwrite($this->dbh,$newcontent,$len);
        //echo $id.'
'.$content.'
'.$len;
    }

    function selectByRid($rid)
    {
        $res=array('id'=>0,'content'=>'');
        if ($rid$this->rcdCnt) return $res;
        else $rcd=$this->getRcd($rid);
        $res[id]=$rcd[id];
        $res[len]=$rcd[len];
        fseek($this->dbh,$rcd[loc]);
        $res[content]=fread($this->dbh,$rcd[len]);
        //$res[rid]=$rid;
        return $res;
    }

    function select($id)
    {
        return $this->selectByRid($this->findByID($id));
    }

    function backup()
    {
        copy($this->path.'/'.$this->name.'.tdb',$this->path.'/'.$this->name.'.tdb.bck');
        copy($this->path.'/'.$this->name.'.indx',$this->path.'/'.$this->name.'.indx.bck');
        copy($this->path.'/'.$this->name.'.lft',$this->path.'/'.$this->name.'.lft.bck');
    }

    function recover()
    {
        copy($this->path.'/'.$this->name.'.tdb.bck',$this->path.'/'.$this->name.'.tdb');
        copy($this->path.'/'.$this->name.'.indx.bck',$this->path.'/'.$this->name.'.indx');
        copy($this->path.'/'.$this->name.'.lft.bck',$this->path.'/'.$this->name.'.lft');
    }
}

?>

 

PS: 其他可以参考上一篇文章:http://blog.csdn.net/heiyeshuwu/archive/2006/06/16/804265.aspx

 


 



陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱工具

MantisBT

MantisBT

Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

SublimeText3 Linux新版

SublimeText3 Linux新版

SublimeText3 Linux最新版

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

Atom編輯器mac版下載

Atom編輯器mac版下載

最受歡迎的的開源編輯器

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)