• 关键词匹配项目深入研究(二)- 分表思想的引入


    (二)分表思想的引入

    近期的文章: 1)高并发数据采集的架构应用(Redis的应用)

                        2)高可用数据采集平台(如何玩转3门语言php+.net+aauto)

    手把手教你做关键词匹配项目这块基本已经完成,深入研究是对系统的性能作为分析,在一些环境的刺激下所必需要做的一些改变。

    手把手教你做关键词匹配项目: 手把手教你做关键词匹配项目(搜索引擎)---- 第一天~手把手教你做关键词匹配项目(搜索引擎)---- 第二十二天 (共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);
        }
    }

    总结
          小帅帅又学到了新的知识点,这是要犒劳于老大的节奏吗?你们是否也要犒劳下我呢,求赞哈!

  • 相关阅读:
    vue生命周期总结
    Generator的基本用法
    React context基本用法
    盗链
    Linux 黑白界面显示
    nginx 反向代理Apache
    apache+php windows下配置
    正则表达式匹配空行
    列表页条目不刷新删除
    linux终端自定义设置
  • 原文地址:https://www.cnblogs.com/oshine/p/4199137.html
Copyright © 2020-2023  润新知