Recently, I was working on a multi-level distribution management system based on likes. All members of the store had likes mall and used likes API to achieve their performance. However, likes provided only one level of distribution, therefore, this system is created. Taking into account the workload reduction and clarifying the hierarchy, we adopt the OOP design method to encapsulate databases and tables as inheritance tables, such as distribution members and storefronts.
However, serious performance problems occur when listing sales reports and distributors. Because the performance rewards of distributors are linked to their lower-level distributors, when encapsulating databases, DFS traversal is performed to obtain the relationship tree of all distributors. However, this relationship is not required when listing sales reports, and DFS spends a lot of time on the php language, as a result, it takes more than 10 seconds to open a page. Therefore, the first step of optimization is to set the DFS switch in the database encapsulation function:
This is part of the implementation of the Database class, and some of the sensitive data has been hidden.
<?phpnamespace System;require_once('KdtApiClient.php');class Database{const db_adr="";const db_usr="";const db_pwd="";const db_db="";public $member=array();public function init($dfs=true,$store=true){$mysqli=new \mysqli(self::db_adr,self::db_usr,self::db_pwd,self::db_db);if($mysqli->connect_error) throw new Exception('Connect Error (' . $mysqli->connect_errno . ') ' . $mysqli->connect_error);$result=$mysqli->query("select `id` from member_new");$row=$result->fetch_array();$i=0;while($row){$this->member[$i]=new Member($row[0],$dfs,$store);$row=$result->fetch_array();$i++;}$mysqli->close();}static public function doQuery($string){$mysqli=new \mysqli(self::db_adr,self::db_usr,self::db_pwd,self::db_db);if($mysqli->connect_error) throw new Exception('Connect Error (' . $mysqli->connect_errno . ') ' . $mysqli->connect_error);return $mysqli->query($string);}static public function querySell($start,$end) {}}
The member class is inherited from the Table:
class Table{public $data=array();protected $table_name;public function __construct($id){$this->data['id']=$id;$mysqli=new \mysqli(Database::db_adr,Database::db_usr,Database::db_pwd,Database::db_db);if($mysqli->connect_error) throw new Exception('Connect Error (' . $mysqli->connect_errno . ') ' . $mysqli->connect_error);$result=$mysqli->query("select * from ".$this->table_name." where `id`=$id");$row=$result->fetch_assoc();$this->data=$row;$mysqli->close();}public function updateAll()//Do NOT CHANGE ID!!!{reset($this->data);while($data=each($this->data)){$querystring="update ".$this->table_name." set `".$data[0]."`='$data[1]' where `id`='".$this->data['id']."'";Database::doQuery($querystring);}reset($this->data);}public function update($key){$querystring="update ".$this->table_name." set `$key`='".$this->data[$key]."' where `id`='".$this->data['id']."'";Database::doQuery($querystring);}public function set($key,$data)//recommended{$this->data[$key]=$data;$this->update($key);}public function get($key)//recommended{return $this->data[$key];}}
It encapsulates basic operations on the table and simplifies subsequent code writing. the following member class constructor can complete the DFS function. After the parameter is set, you can greatly improve the efficiency without using DFS in some scenarios:
class Member extends Table{protected $table_name="member_new";public $infer=array();public $store=array();public function __construct($id,$dfs=true,$store=true){parent::__construct($id);$mysqli=new \mysqli(Database::db_adr,Database::db_usr,Database::db_pwd,Database::db_db);if($mysqli->connect_error) throw new Exception('Connect Error (' . $mysqli->connect_errno . ') ' . $mysqli->connect_error);if($dfs){$result=$mysqli->query("select `id` from ".$this->table_name." where `super`=".$this->data['id']);if($result){$row=$result->fetch_array();$i=0;while($row){$this->infer[$i]=new Member($row[0]);$row=$result->fetch_array();$i++;}}}if($store){$result=$mysqli->query("select `id` from store_new where `member`=".$this->data['id']);if($result){$row=$result->fetch_array();$i=0;while($row){$this->store[$i]=new Store($row[0]);$row=$result->fetch_array();$i++;}}}$mysqli->close();}
(Some sensitive functions are hidden)
In addition, the cache support is added to the php script for front-end AJAX response, because the api calling speed of likes is slow, however, such distribution mall data does not require high real-time performance, so the server cache method is used to reduce the speed of like communication. in addition, the localized object instead of reading information from the remote database also reduces the cost of querying the database. the implementation of the Cache object is as follows:
<?phpnamespace System; class Cache { public function __construct() { } static public function readCache($string) {error_reporting(1); $file=fopen($string.".ser","r"); if(!$file)return false; $ser=fread($file,filesize($string.".ser")); fclose($file); $array=array(); $array=unserialize($ser); if(time()-$array['time']>3600*24)return false; return $array['data']; } static public function updateCache($string,$data) { $array=array(); $array['time']=time(); $array['data']=$data; $file=fopen($string.".ser","w"); fwrite($file,serialize($array)); fclose($file); } }
The backend AJAX response page selects to obtain local data based on the Cache feedback or requests the server to update local data:
<?phprequire_once('System/db.php');require_once('System/cache.php');use \System\Database;use \System\Cache;switch($_GET['action']){case 'num':$result=Database::doQuery("select count(*) from member_new");$row=$result->fetch_array();echo $row[0];exit(0);case 'get':if($array=Cache::readCache("member")){echo json_encode($array);}else{$db=new Database();$db->init(false,true);$arr=array();for($i=0;$i<count($db->member);$i++){$arr[$i]=array();$arr[$i]=$db->member[$i]->data;$arr[$i]['password']=null;$arr[$i]['name']=iconv("GBK","utf-8",$arr[$i]['name']);$arr[$i]['nickname']=iconv("GBK","utf-8",$arr[$i]['nickname']);$arr[$i]['sell']=$db->member[$i]->getSell();}Cache::updateCache("member",$arr);echo json_encode($arr);}exit(0);
After the above optimization, the original response time is around 15 s, and now the response time is about S.
Copyright Disclaimer: This article is an original article by the blogger and cannot be reproduced without the permission of the blogger.