최근에는 Youzan을 기반으로 한 다단계 유통 관리 시스템을 작업하고 있습니다. 모든 회원 매장은 Youzan Mall에 있으며 Youzan API를 사용하여 실적을 얻습니다. 그러나 Youzan은 한 단계의 유통만 제공하므로 이 시스템은 생성되었습니다. 작업량을 줄이고 계층적 관계를 명확하게 하기 위해 데이터베이스와 테이블을 기본 클래스, 배포 구성원, 상점 및 기타 상속 테이블로 캡슐화하는 OOP 설계 방법이 채택되었습니다.
그러나 판매 보고서 및 유통업체 나열 시 심각한 성능 문제가 발생했습니다. 유통업체의 성과 보상은 하위 유통업체와 연결되어 있으므로 데이터베이스를 캡슐화할 때 모든 유통업체의 관계 트리를 얻기 위해 DFS 순회를 수행했습니다. 그러나 판매 보고서를 나열할 때는 이러한 관계가 필요하지 않습니다. DFS는 PHP 언어에 많은 시간을 소비하므로 페이지를 여는 데 10초 이상 걸리므로 최적화의 첫 번째 단계는 설정하는 것입니다. 데이터베이스 캡슐화 기능의 DFS 스위치:
이는 일부 민감한 데이터가 숨겨져 있는 Database 클래스의 부분 구현입니다.
<?php namespace 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) {} }
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]; } }
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(); }
또한, 프론트엔드 AJAX에 대응하는 PHP 스크립트에 캐싱 지원이 추가되어 있습니다. 그러나 Youzan의 API 호출 속도가 느리기 때문에 이런 배포몰의 데이터는 높은 실효성을 가지지 못합니다. 서버 캐싱은 Youzan과의 통신으로 인한 속도 저하를 줄이기 위해 사용됩니다. 또한 지역화된 개체가 원격 데이터베이스의 정보 읽기를 대체하므로 데이터베이스 쿼리 비용도 절감됩니다. 다음과 같이 객체를 직렬화합니다. 코드는 서버에 로컬로 저장됩니다.
<?php namespace 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); } }
<?php require_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);
저작권 안내: 이 글은 블로거의 원본 글이며, 블로거의 승인을 받지 않은 글입니다.
위 내용은 콘텐츠 측면을 포함하여 다단계 배포 도킹 타사 API 데이터 수집 시스템의 최적화를 소개합니다. PHP 튜토리얼에 관심이 있는 친구들에게 도움이 되기를 바랍니다.