无视界-个人小站
php分表缓存数据,空间换效率

电子市场由于数据较多,且区分主表、OEM表、正版软件表这三种数据,前一阵子老是反映里面有很多软件会重复,特别是搜索时,由于搜索三个表,所以造成数据重复。。。
主要表现在,因为存在分页,不可能把库都遍历一次来每个用户去一次重。。所以加缓存临时表显得刻不容缓。。

缓存表分二张:
第一张,用于记录缓存的ID还有过期时间等等信息。

-- 表的结构 sj_cache

CREATE TABLE IF NOT EXISTS sj_cache (
id int(11) NOT NULL AUTO_INCREMENT,
cache_id varchar(32) NOT NULL,
created int(11) NOT NULL,
expired int(11) NOT NULL,
PRIMARY KEY (id)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=0;


第二张,存放具体数据模板表

-- 表的结构 sj_cache_soft

CREATE TABLE IF NOT EXISTS sj_cache_soft (
id int(11) NOT NULL AUTO_INCREMENT,
cacheid int(11) NOT NULL,
oemid int(11) NOT NULL DEFAULT '0',
softname varchar(255) DEFAULT NULL,
mips smallint(6) NOT NULL DEFAULT '0',
x86 smallint(6) NOT NULL DEFAULT '0',
md5 varchar(32) DEFAULT NULL,
ico varchar(255) DEFAULT NULL,
ico1 varchar(255) NOT NULL,
author varchar(255) DEFAULT NULL,
description varchar(255) DEFAULT NULL,
content text,
star smallint(6) DEFAULT '6',
resolution varchar(50) NOT NULL,
platform varchar(10) DEFAULT NULL,
packageid varchar(70) DEFAULT NULL,
fullscreen smallint(6) DEFAULT NULL,
minsdkversion smallint(6) NOT NULL,
targetsdkversion smallint(6) NOT NULL,
uses_permission text NOT NULL,
PRIMARY KEY (id),
KEY ix_packageid (packageid),
KEY oemid (oemid),
KEY x86 (x86),
KEY mips (mips),
KEY cacheid (cacheid)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=0 ;

程序设计上如果把所有数据都存在这张表里。这个表会很大,做了下测试,开放一个小时,这个表的数据达到188万条记录,所以要实现分表。。

首先,得有一个函数来实现分表的创建与返回表名的过程 ,因为如果每次去库中查询表是否存在会严重影响性能,所以需要memcached缓存住那些已经存在了,具体实现过程如下。

 /**  
  * 返回缓存表名以及创建表过程  
  * @param <type> 缓存KEYID  
  * @return string 缓存表名称  
  */  
 function __getCacheTable($keyname=''){  
     if (!$keyname) return cache_soft;  
     //从mem中读入是否有该表名  
     $tbName=$this->mem->getCache($keyname);  
     if (!$tbName){  
         $tbName=cache_soft_.substr($keyname,-1);  
         //查询缓存表是否存在  
         $query=$this->db->query($sql=show tables like 'sj_$tbName');  
         $result=$this->db->fetch_array($query);  

         //如果不存在,则用模板表结构创建新的表  
         if (!$result){  
             $query=$this->db->query($sql=show create table sj_cache_soft);  
             $result=$this->db->fetch_array($query);  
             $sql=str_replace('sj_cache_soft','sj_'.$tbName,$result['Create Table']);  
             $this->db->query($sql);  
             //把表名放入mem缓存  
             $this->mem->setCache($keyname, $tbName,360000);  
         }  
     }  

     return $tbName;  

 }  

应用过程片段。

for ($number = 0; $number <= 1;="" $number++)=""></=>
//缓存cacheid
$db_cache_id = substr(md5($rootid . $categoryid . $flag), 8, 16);
//缓存表名称
$db_cache_table=$this->__getCacheTable($db_cache_id);
//缓存查询
$dbCache = $this->selecttable('cache', '*', array(
'cache_id' => $db_cache_id
), 'limit 1');
if ($dbCache) {
$cacheid = $dbCache[0]['id'];
$this->data ['soft'] = array();
// 从缓存中开始分页查询
if (time () < $dbcache="" [0]['expired'])="">
$pagesize = $this->data ['CLIENT_SOFT_PAGESIZE'];
$orders = array(
'commend',
'hots',
'id'
);
$Order = $orders [$flag];

     $sql = select * from  . $this->tname($db_cache_table) .  where cacheid={$cacheid};  
     if (!$flag) {  
         $sql .=  and commend=1;  
     }  
     if (strpos($arch,'x86')!==false){  
         $sql .=  and x86=1;  
     }  
     if (strpos($arch,'mips')!==false){  
         $sql .=  and mips=1;  
     }  
     $query = str_replace(*, count(0), $sql);  

     $ret = $this->db->query($query);  
     $result = $this->db->fetch_row($ret);  
     $softcount = $result[0];  

     $pageCount = intval($softcount / $pagesize);  
     if ($softcount % $pagesize)  
         $pageCount++;  
     $this->data ['pCount'] = $pageCount;  

     $sql .=  order by {$Order} desc;  
     $limit =  LIMIT  . ($page - 1) * $pagesize . ',' . $pagesize;  
     // 组装sql  
     $sql .= $limit;  
     if ($this->debug) var_dump($sql);  
     $ret = $this->db->query($sql);  

     while ($row = $this->db->fetch_array($ret)) {  
         if (!$row ['packageid'])  
         continue;  
         $this->data ['soft'][] = $row;  
     }  
     $isDbCache = true;  
     //如果缓存表数据返回,则跳出循环。  
     break;  
     }  
 }  

 //以下是从原数据查询结果  
 ###########缓存处理中  
 $this->deletetable('cache', array('cache_id' => $db_cache_id));  
 $this->deletetable($db_cache_table, array('cacheid' => $cacheid));  
 $cacheid = $this->inserttable('cache', array('cache_id' =>  $db_cache_id, 'created' => time(), 'expired' => time() + 3600),  1);  
 // ########################################3  
 foreach ($iSql as $query) {  

     // 组装sql  
     $sql = $query . $orderby;  
     $ret = $this->db->query($sql);  

     while ($row = $this->db->fetch_array($ret)) {  
     if (!$row ['packageid'] or in_array($row['packageid'], $ExistPacks))  
         continue;  
     $this->data ['soft'][] = $row;  
     unset($row['id']);  
     $row['cacheid'] = $cacheid;  
     //把本条数据插入缓存表  
     $this->inserttable($db_cache_table, $row);  
     $ExistPacks[] = $row['packageid'];  
     }  
 }  

}

这样下来系统的缓存会多达36个,这是以空间换取效率的一种办法,目前看来效率还是挺好的。。。

php分表缓存数据,空间换效率