PHP Conference 2014に参加しました-そのに-

  • 投稿者:
  • 投稿カテゴリー:MySQL / PHP

ざっくりまとめ、その後自分でやってみたことも含む、ほぼパクリ

mysqlnd 徹底解説 do_akiさん

mysqlndについて

MySQL client libraryはたくさん(ZendDB、PEAR_DB…)あるが、必ず
・mysql extension:php4の時代から使えた古くからある拡張
・mysqli extension:mysql 拡張を刷新する形でphp5から利用可能なモジュール
・pdo extension:それ自身がDB 抽象層であり、配下に多くの DBMS に対応したドライバが存在、そのなかのひとつがmysql
を呼び出している
これらがMySQLと直接やり取りするかといえばそうでもなく
mysqlnd / libmysql → アクセスやプロトコル判断など
mysql / mysqli / pdo → 実際に接続
となり、詳しくは下図
Screenshot 2014-10-13 at 02.36.06

mysqlnd vs libmysql

・libmysqlはMySQL側が用意しているライブラリで、MySQL利用者に対してC言語レベルでのAPIを提供する、Oracle(MySQL AB)からある枯れた技術、しかしGPLv2ライセンス
・mysqlndはZend Engine内に存在する。MySQL Native Driverという、PHPの拡張モジュールとして実装された、MySQLのネイティブクライアント
 比較的新しくmysql4.1以前には接続できない
 またlibmysqlと違い、my.cnfを読み込まないため、設定によっては文字コードで影響があるかも。プラグイン(mysqlnd_ms)でロードバランシング可能、問題なく動作するらしい
Screenshot 2014-10-13 at 02.46.30

php5.4移行はmysqlndがデフォルトとなり、libmysqlはオプションとなった
(libmysqlは非推奨となったわけではない)

root@hostname:/etc/apt# php -i | grep mysqlnd 
Additional .ini files parsed => /etc/php5/cli/conf.d/10-mysqlnd.ini,
Client API version => mysqlnd 5.0.10 - 20111026 - $Id: b0b3b15c693b7f6aeb3aa66b646fee339f175e39 $
Client API library version => mysqlnd 5.0.10 - 20111026 - $Id: b0b3b15c693b7f6aeb3aa66b646fee339f175e39 $
mysqlnd
mysqlnd => enabled
Version => mysqlnd 5.0.10 - 20111026 - $Id: b0b3b15c693b7f6aeb3aa66b646fee339f175e39 $
Loaded plugins => mysqlnd,example,debug_trace,auth_plugin_mysql_native_password,auth_plugin_mysql_clear_password
mysqlnd statistics =>  
Client API version => mysqlnd 5.0.10 - 20111026 - $Id: b0b3b15c693b7f6aeb3aa66b646fee339f175e39 $

パフォーマンスについて

Screenshot 2014-10-13 at 11.40.14

メモリ使用量はmysqlndのほうが少ない
mysqlndについてはmysqli/pdoを経由しないため、メモリ使用量が半分になる
memory_get_usageではmysqli/pdoでのメモリ使用量は計上するが、libmysqlにてのメモリを計上しないため、メモリ使用量が変わらないようにみえる

ただしmysqlndについて、大きなテーブルを乗せるとメモリ使用長が大きくなるため注意
これは仕様とされており、php5.6からは回避可能、しかしmysqliを利用する必要がある

どちらが早いかやってみた

php5-mysql vs php5-mysqlnd

root@hostname:/usr/local/src# wget -d http://php5.up.seesaa.net/web/T01Prefecture.zip
...
root@hostname:/usr/local/src# unzip T01Prefecture.zip 
Archive:  T01Prefecture.zip
  inflating: T01Prefecture.sql 
root@hostname:/usr/local/src# mysql -uroot SampleDB050 < T01Prefecture.sql 
root@hostname:/usr/local/src# cat /var/www/htdocs/index.php 
<?php
  $url = "localhost";
  $user = "root";
  $pass = "";
  $db = "SampleDB050";

  $start = microtime(true);
  $max = 1000;

  for($i = 0; $i < $max; $i++) {   
  // MySQLへ接続する
  $link = mysql_connect($url,$user,$pass) or die("MySQLへの接続に失敗しました。");
  // データベースを選択する
  $sdb = mysql_select_db($db,$link) or die("データベースの選択に失敗しました。");
  // クエリを送信する
  $sql = "SELECT * FROM T01Prefecture";
  $result = mysql_query($sql, $link) or die("クエリの送信に失敗しました。<br />SQL:".$sql);
  //結果セットの行数を取得する
  $rows = mysql_num_rows($result);
  //結果保持用メモリを開放する
  mysql_free_result($result);
  // MySQLへの接続を閉じる
  mysql_close($link) or die("MySQL切断に失敗しました。");
  }

  $end = microtime(true);
  $tm = $end - $start;
  echo $tm;
?>
#####
実行したところphp5-mysqlが0.5秒前後、php5-mysqlndが0.7秒前後とphp5-mysqlが早いという切ない結果に終わった
おそらく接続方法(mysql_connect)によるものだと思われる
#####

root@hostname:/usr/local/src# cat /var/www/htdocs/index2.php 
<?php
  $url = "localhost";
  $user = "root";
  $pass = "";
  $db = "SampleDB050";

  $start = microtime(true);
  $max = 1000;

  for($i = 0; $i < $max; $i++) {   
  // MySQLへ接続する
  $mysqli = new mysqli($url,$user,$pass,$db);
  if (mysqli_connect_error()) {
  die('接続失敗です。'.mysqli_connect_error());
  }
  // MySQLへの接続を閉じる
  $mysqli->close();
  }

  $end = microtime(true);
  $tm = $end - $start;
  echo $tm;
?>

#####
実行したところphp5-mysqlが0.30秒前後、php5-mysqlndが0.35秒前後とphp5-mysqlが少し早いという切ない結果に終わった
PG力のなさが出ているため、また機会があれば試す
#####

参考URL

MySQL と PHP の間を詳しく見てみる
http://d.hatena.ne.jp/do_aki/20111214/1323831558