(二)分表思想的引入php
近期的文章: 1)高并发数据采集的架构应用(Redis的应用)html
2)高可用数据采集平台(如何玩转3门语言php+.net+aauto)mysql
手把手教你作关键词匹配项目这块基本已经完成,深刻研究是对系统的性能做为分析,在一些环境的刺激下所必须要作的一些改变。sql
手把手教你作关键词匹配项目: 手把手教你作关键词匹配项目(搜索引擎)---- 第一天~手把手教你作关键词匹配项目(搜索引擎)---- 第二十二天 (共22篇)数据库
深刻研究:上节讲到 关键词匹配项目深刻研究-过滤器的引入。性能优化
每一篇会分为问题的前因、解决方案以及有些必要的实现方案。架构
本篇正文正式开始。并发
问题的前因高并发
随着自动采集数据的爆炸式的增加,词库的容量蒸蒸日上,一下从几W数据猛增几百万数据,小帅帅看着数据库的查询愈来愈感到无能为力。性能
再加上小丁丁常对小帅帅说的最多的一句:什么时候那么选词能快一点,每次我都等很久都莫有反应,真是急死我了。
小帅帅也比较焦急,心力憔悴,真正的感受到原来这就是挑战。小帅帅迫不得已的继续找到于老大,求于老大赏赐高招。
于老大拍拍小帅帅的肩膀:小伙子,知道项目的难度了吧!
小帅帅回答道:别挖苦我了,我已深深的感觉到了,我想我心脏估计快承受不了了。
于老大:就这点你就承受不了,那估计之后有的是给你受的。
小帅帅:大哥,别说这些虚的行不,赶忙的解决方案丫。
于老大:急啥,事情是急不来的,过来,哥给你指条明路。
“每一个宝贝是否是有类别的属性,那么这几百万数据真正属于这个类别的词可以有多少?假设咱们只取这个类别的词库咱们的项目是否能够继续稳定下来”。
解决方案
按照某种业务须要,咱们能够对数据表实行分割,能够纵向或者横向分割,能够有效的进行性能优化。
纵向分割也称列分割,把不经常使用的列或者长字段分割来保证明体处于一个相对适用的状态,常见的有一对一关联。
横向分割也称行分割,按照某种业务拆分数据的记录来存放在不一样的表,常见的有按日期分表操做。
本案例是使用横向分割,把数据按照类别的形式进行拆分。
实现方案
咱们为了避免更改数据表的结构,这样设计了,咱们按照表名来区分项目使用那个数据表。这样一来的改动相对是很是少的。咱们只需稍微改动下代码就能够解决了,这很心塞的一件事情。
修改Keyword的代码,增长获取数据源。
<?php define('DATABASE_HOST','127.0.0.1'); define('DATABASE_USER','xiaoshuaishuai'); define('DATABASE__PASSWORD','xiaoshuaishuai'); define('DATABASE_CHARSET','utf-8'); class Keyword { public $word; public static $conn = null; public function getDbConn(){ if(self::$conn == null){ self::$conn = mysql_connect(DATABASE_HOST,DATABASE_USER,DATABASE__PASSWORD); mysql_query("SET NAMES '".DATABASE_CHARSET."'",self::$conn); mysql_select_db("dict",self::$conn); return self::$conn; } return self::$conn; } public function save(){ $sql = "insert into keywords(word) values ('$this->word')"; return mysql_query($sql,$this->getDbConn()); } public static function getWordsSource($cid,$limit=0,$offset=40){ $sql = "SELECT * FROM keywords_$cid LIMIT $limit,$ffset"; return DB::MakeArray($sql); } public static function getWordsCount($cid){ $sql = "SELECT count(*) FROM keywords_$cid"; return DB::QueryScalar($sql); } }
DB类新增QueryScalar,用于算总量
<?php #@author oShine define('DATABASE_HOST','127.0.0.1'); define('DATABASE_USER','xiaoshuaishuai'); define('DATABASE__PASSWORD','xiaoshuaishuai'); define('DATABASE_CHARSET','utf-8'); class DB { public static $conn = null; public static function Connect(){ if(self::$conn == null){ self::$conn = mysql_connect(DATABASE_HOST,DATABASE_USER,DATABASE__PASSWORD); mysql_query("SET NAMES '".DATABASE_CHARSET."'",self::$conn); mysql_select_db("dict",self::$conn); return self::$conn; } return self::$conn; } public static function Query($sql){ return mysql_query($sql,self::Connect()); } public static function makeArray($sql){ $rs = self::Query($sql); $result = array(); while($data = mysql_fetch_assoc($rs)){ $result[] = $data; } return $result; } public static function QueryScalar($sql){ $rs = self::Query($sql); $data = mysql_fetch_array($rs); if($data == false || empty($data) || !isset($data[1])) return 0; return $data[1]; } }
修改Selector的代码,用于选词:
<?php #@Filename:selector/Selector.php #@Author:oshine require_once dirname(__FILE__) . '/SelectorItem.php'; require_once dirname(__FILE__) . '/charlist/CharList.php'; require_once dirname(__FILE__) . '/charlist/CharlistHandle.php'; require_once dirname(dirname(__FILE__)) . '/lib/Logger.php'; class Selector { private static $charListHandle = array( "黑名单" => "BacklistCharListHandle", "近义词" => "LinklistCharListHandle" ); public static function select($num_iid) { $selectorItem = SelectorItem::createFromApi($num_iid); Logger::trace($selectorItem->props_name); $charlist = new CharList(); foreach (self::$charListHandle as $matchKey => $className) { $handle = self::createCharListHandle($className, $charlist, $selectorItem); $handle->exec(); } $selectWords = array(); $wordsCount = Keyword::getWordsCount(selectorItem->cid); $offset = 40; $page = ceil($wordsCount/$offset); for($i=0;$i<=$page;$i++){ $limit = $i*$offset; $keywords = Keyword::getWordsSource(selectorItem->cid,$limit,$offset); foreach ($keywords as $val) { # code... $keywordEntity = SplitterApp::split($val["word"]); # code... if(MacthExector::macth($keywordEntity,$charlist)){ $selectWords[] = $val["word"]; } } } return $selectWords; } public static function createCharListHandle($className, $charlist, $selectorItem) { if (class_exists($className)) { return new $className($charlist, $selectorItem); } throw new Exception("class not exists", 0); } }
总结 小帅帅又学到了新的知识点,这是要犒劳于老大的节奏吗?大家是否也要犒劳下我呢,求赞哈!