安価なホスティングの高負荷:MySQLのハッシュテーブル

負荷の高いプロジェクト(Webサイト)は、必ずしも人気のあるソーシャルネットワーク、ビデオホスティング、またはMMORPGではありません。 サイトのハードウェア要件を劇的に増やす最も簡単な方法は、セッションストレージをデータベースに転送することです。 この記事では、パフォーマンスを犠牲にすることなく、データベースにデータを保存する方法を見ていきます。 少量のRAMを犠牲にすると、CPU時間を大幅に節約できます。 memcachedやその他の特別なキャッシュツールが利用できない状況について話している。



魔法の記憶テーブル



MySQL DBMSは、常にRAMに保存されるタイプのテーブルを実装しているため、常に最小限の時間で利用できます。 これはMEMORYであり、HEAPと同義です。 2番目の名前は古いため、最初の名前を使用することをお勧めします。

MyISAMやInnoDBと比較すると、この形式は非常に限られていますが、運用データを完全に保存するタスクに対応していますが、伝統的に長所と短所を挙げ、長所から始めます。

  1. クエリは可能な限り迅速に実行されます-データは既にメモリ内にあります
  2. テーブルはすぐに作成され、すぐに破棄されます。
  3. 各テーブルのサイズを制限する機能
  4. サポートされるロック


3番目と4番目のパラグラフでは、MEMORYテーブルを、たとえばMemcacheと区別しています。1つのサーバーが1つのハッシュテーブルを表し、任意のブロックの可能性も本格的なDBMSの特徴です。 当然、この利点で終わります。

かなり深刻な欠点がいくつかあります。

  1. TEXTおよびBLOBフィールドタイプは使用できません


データ保存



この状況では、最適なフィールドタイプはVARCHARです。 MySQL 5.0.3の時点では、このタイプのフィールドは65535バイトの長さにすることができます-同じセッションを保持するには十分です。 このタイプのストレージに共通するのは、Set、Get、Check、Deleteの各操作です。 REPLACEクエリを使用してSetメソッドを実装し、SELECT COUNT(*)を使用してチェックします。残りはすべて明確です。

したがって、テーブルを作成します。



CREATE TABLE `hashtable` (

`key` VARCHAR(32),

`value` VARCHAR(65536),

PRIMARY KEY (`key`)

) ENGINE=MEMORY DEFAULT CHARSET=utf8 COLLATE utf8_bin;








では、PHPに移りましょう。



ハッシュテーブルオブジェクトインターフェイス



シンプルな構造のおかげで、インターフェイスは非常に原始的です。 唯一の注意点は、配列とオブジェクトの両方を保存する必要があるためすべての入力値(値)のシリアル化です。 したがって、理想的なバージョンへの近似は次のようになりました。

 <?php class HashTable { //     MySQL protected $connect; //   protected $table; /** * * @param resource MySQL $connect * @param string $table */ public function __construct($connect, $table) { $this->connect = $connect; $this->table = $table; } /** * * @param string $key * @param string $val * @return boolean */ public function set($key, $val) { $key = md5($key); $val = serialize($val); $val = mysql_real_escape_string($val, $this->connect); $query = 'REPLACE INTO `'.$this->table.'` (`key`, `value`) '; $query .= 'VALUES ("'.$key.'", "'.$val.'")'; return mysql_query($query, $this->connect) ? true : false; } /** * * @param string $key * @return void */ public function get($key) { $key = md5($key); $query = 'SELECT `value` FROM `'.$this->table.'` WHERE `key`="'.$key.'"'; $result = mysql_query($query, $this->connect); if ($result) { $row = mysql_fetch_row($result); return unserialize($row[0]); } else { return false; } } /** * * @param string $key * @return boolean */ public function check($key) { $key = md5($key); $query = 'SELECT COUNT(*) FROM `'.$this->table.'` WHERE `key`="'.$key.'"'; $result = mysql_query($query, $this->connect); $row = mysql_fecth_row($result); return (bool)$row[0]; } /** * * @param string $key * @return boolean */ public function delete($key) { $key = md5($key); $query = 'DELETE FROM `'.$this->table.'` WHERE `key`="'.$key.'"'; return mysql_query($query, $this->connect) ? true : false; } }
      
      





使用例:

 <?php //  $link = mysql_connect('localhost'); mysql_select_db('test', $link); mysql_set_charset('utf8', $link); $storage = new HashTable($link, 'hashtable'); //  $storage->set('name', 'Vasya'); //  var_dump($storage->check('name')); //  var_dump($storage->get('name')); //  $storage->delete('name'); //  var_dump($storage->check('name'));
      
      





結論として


このソリューションは、少量の情報を保存するためだけのものであることに注意してください。 MEMORYテーブルに大量のデータをロードすると、スワップが発生する可能性があり、さらに悪いことに、ディスクに保存されているテーブルを照会するためのリソースをサーバーから奪います。 その結果、要求の操作データもスワップを通過する可能性があり、これはDBMS全体のパフォーマンスに大きく影響します。 さらに、テーブルのボリューム制限に達すると、古いレコードは自動的に削除されず、サーバーは単にエラーを返します。 一方、数メガバイトは、過去1時間の訪問やサイト上のユーザーの位置に関する詳細な統計に簡単に適合することができます。



All Articles