(二)分表思想的引入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); } }
總結 小帥帥又學到了新的知識點,這是要犒勞於老大的節奏嗎?大家是否也要犒勞下我呢,求贊哈!