ラベル handlersocket の投稿を表示しています。 すべての投稿を表示
ラベル handlersocket の投稿を表示しています。 すべての投稿を表示

2012年5月3日木曜日

Macにmysql5.5.14とspiderとhandlersocketを入れる

■モチベーション
spiderとhandlersocketでスケーラブルかつキャッシュいらずなmysql作れないかな。
# spider2.24からhandlersocketと一緒に使えるそうだ。
# 入れてみよう。
http://wild-growth-ja.blogspot.jp/2011/02/mysqlspidervpotherspider-224-vp-013.html

■結果概要
・インストールと、spider, handlersocketの単体の動作は問題なくできた。
・spider経由でMySQL::sandbox上のテーブルにhandlersocketで接続することができなかった。(調査中)
※ 本来はhandlersocketを使ってspiderのテーブルにアクセスできるはずだが。

■備考
mysqlはhomebrewで入れたかったけど、spiderを5.5系に入れる場合はソースから入れる方法しかなく、
なので、仕方なくmysqlとspiderを両方ソースから入れました。
mysqlとspiderとhandlersocketとq4mなども一緒にしたソースを下記から取得できますが、Macでのインストールではいろいろ苦戦。
https://launchpad.net/spiderformysql/spider-2.x/2.28-for-5.5.14


■前準備
# brewが入っていなければ
## /usr/bin/ruby -e "$(/usr/bin/curl -fksSL https://raw.github.com/mxcl/homebrew/master/Library/Contributions/install_homebrew.rb)"

# cmakeやwgetが入っていない人は
## brew install cmake
## brew install wget

■まずはmysqlとspiderをインストール

# ダウンロード
https://launchpad.net/spiderformysql/spider-2.x/2.28-for-5.5.14
mysql-5.5.14-spider-2.28-vp-0.17-hs-1.1-q4m-0.95.tgz

# macで綺麗に動いてくれないので、少し修正する。
http://bugs.mysql.com/bug.php?id=65050
http://lists.mysql.com/commits/140413

# q4mとhandlersocketもmacで綺麗にmakeしてくれないので、削除。(handlersocketは後で別で入れる)
mv storage/q4m ~/bk
mv plugin/handlersocket ~/bk

# configure
cmake -DCMAKE_INSTALL_PREFIX=/usr/local/mysql-5.5.14-spider \
        -DMYSQL_DATADIR=/var/lib/mysql/data \
        -DMYSQL_UNIX_ADDR=/var/lib/mysql/mysql.sock \
        -DDEFAULT_CHARSET=utf8 \
        -DWITH_EXTRA_CHARSETS=complex \
        -DDEFAULT_COLLATION=utf8_general_ci \
        -DWITH_PARTITION_STORAGE_ENGINE=1 \
        -DWITHOUT_ARCHIVE_STORAGE_ENGINE=1 \
        -DWITHOUT_BLACKHOLE_STORAGE_ENGINE=1 \
        -DWITHOUT_EXAMPLE_STORAGE_ENGINE=1 \
        -DWITHOUT_FEDERATED_STORAGE_ENGINE=1 \
        -DWITH_PIC=1 .

# makeするも失敗。
sudo make 
[ 93%] Building C object unittest/mysys/CMakeFiles/my_atomic-t.dir/my_atomic-t.c.o
/var/tmp//cco9mhO6.s:596:suffix or operands invalid for `add'
make[2]: *** [unittest/mysys/CMakeFiles/my_atomic-t.dir/my_atomic-t.c.o] Error 1
make[1]: *** [unittest/mysys/CMakeFiles/my_atomic-t.dir/all] Error 2
make: *** [all] Error 2

# これは解決策が見つからず、-iで無理やりインストール。。。
sudo make -i
sudo make install -i


# 起動スクリプトをコピー
cd /usr/local/mysql-5.5.14-spider
sudo cp support-files/mysql.server bin/

$ spider インストールスクリプトを取得
sudo wget http://launchpad.net/spiderformysql/spider-2.x/2.26-for-5.5.14/+download/spider-init-2.26-for-5.5.14.tgz
tar zxvf spider-init-2.26-for-5.5.14.tgz

# spiderをインストール
mysql -u root < install_spider.sql 
ERROR 1049 (42000) at line 20: Unknown database 'mysql'
# mysqlがない。

#rootでログインしてshow databasesしても、mysqlデータベースがなかった。
sudo ./scripts/mysql_install_db --datadir=/var/lib/mysql/data --user=mysql
# databaseを初期化

# 再度実行
mysql -u root < install_spider.sql 

ERROR 1436 (HY000) at line 211: Thread stack overrun:  13056 bytes used of a 131072 byte stack, and 128000 bytes needed.  Use 'mysqld --thread_stack=#' to specify a bigger stack.
# 次はスタック数のエラー

# 設定ファイル変更
sudo cp support-files/my-small.cnf /etc/my.cnf
vi /etc/my.cnf
thread_stack = 256K

# 再度実行
mysql -u root < install_spider.sql 
# 通った!

mysql> show engines;
+--------------------+---------+------------------------------------------------------------+--------------+------+------------+
| Engine             | Support | Comment                                                    | Transactions | XA   | Savepoints |
+--------------------+---------+------------------------------------------------------------+--------------+------+------------+
| SPIDER             | YES     | Spider storage engine                                      | YES          | YES  | NO         |
| PERFORMANCE_SCHEMA | YES     | Performance Schema                                         | NO           | NO   | NO         |
| InnoDB             | DEFAULT | Supports transactions, row-level locking, and foreign keys | YES          | YES  | YES        |
| MyISAM             | YES     | MyISAM storage engine                                      | NO           | NO   | NO         |
| MRG_MYISAM         | YES     | Collection of identical MyISAM tables                      | NO           | NO   | NO         |
| MEMORY             | YES     | Hash based, stored in memory, useful for temporary tables  | NO           | NO   | NO         |
| CSV                | YES     | CSV storage engine                                         | NO           | NO   | NO         |
+--------------------+---------+------------------------------------------------------------+--------------+------+------------+
7 rows in set (0.00 sec)


■続いてhandlersocket
https://github.com/ahiguti/HandlerSocket-Plugin-for-MySQL

git clone git://github.com/ahiguti/HandlerSocket-Plugin-for-MySQL.git
cd HandlerSocket-Plugin-for-MySQL/

./autogen.sh
./configure --with-mysql-source=/usr/src/mysql-5.5.14-spider-2.28-vp-0.17-hs-1.1-q4m-0.95 --with-mysql-bindir=/usr/local/mysql-5.5.14-spider/bin/ --with-mysql-plugindir=/usr/local/mysql-5.5.14-spider/lib/plugin
make
make install

# 別コンソールでmysqlを起動し、
mysql> install plugin handlersocket soname 'handlersocket.so';
 
# プラグインが入ったかな。
ls /usr/local/Cellar/mysql/5.5.20/lib/plugin/
 
# handlersocketの設定を入れる。
sudo vi /etc/my.cnf 
[mysqld]セクションに追記
handlersocket_port = 9998
handlersocket_port_wr = 9999
handlersocket_address =
handlersocket_verbose = 0
handlersocket_timeout = 300
handlersocket_threads = 16
thread_concurrency = 128
open_files_limit = 65535

mysql> show plugins;
+-----------------------+--------+--------------------+------------------+---------+
| Name                  | Status | Type               | Library          | License |
+-----------------------+--------+--------------------+------------------+---------+
| binlog                | ACTIVE | STORAGE ENGINE     | NULL             | GPL     |
| mysql_native_password | ACTIVE | AUTHENTICATION     | NULL             | GPL     |
| mysql_old_password    | ACTIVE | AUTHENTICATION     | NULL             | GPL     |
| CSV                   | ACTIVE | STORAGE ENGINE     | NULL             | GPL     |
| MEMORY                | ACTIVE | STORAGE ENGINE     | NULL             | GPL     |
| MyISAM                | ACTIVE | STORAGE ENGINE     | NULL             | GPL     |
| MRG_MYISAM            | ACTIVE | STORAGE ENGINE     | NULL             | GPL     |
| InnoDB                | ACTIVE | STORAGE ENGINE     | NULL             | GPL     |
| INNODB_TRX            | ACTIVE | INFORMATION SCHEMA | NULL             | GPL     |
| INNODB_LOCKS          | ACTIVE | INFORMATION SCHEMA | NULL             | GPL     |
| INNODB_LOCK_WAITS     | ACTIVE | INFORMATION SCHEMA | NULL             | GPL     |
| INNODB_CMP            | ACTIVE | INFORMATION SCHEMA | NULL             | GPL     |
| INNODB_CMP_RESET      | ACTIVE | INFORMATION SCHEMA | NULL             | GPL     |
| INNODB_CMPMEM         | ACTIVE | INFORMATION SCHEMA | NULL             | GPL     |
| INNODB_CMPMEM_RESET   | ACTIVE | INFORMATION SCHEMA | NULL             | GPL     |
| PERFORMANCE_SCHEMA    | ACTIVE | STORAGE ENGINE     | NULL             | GPL     |
| partition             | ACTIVE | STORAGE ENGINE     | NULL             | GPL     |
| SPIDER                | ACTIVE | STORAGE ENGINE     | ha_spider.so     | GPL     |
| handlersocket         | ACTIVE | DAEMON             | handlersocket.so | BSD     |
+-----------------------+--------+--------------------+------------------+---------+
19 rows in set (0.01 sec)
# よし、両方入った


■spiderを使ってみる

# ここを参考に、MySQL::sandboxを立ち上げる
http://nippondanji.blogspot.jp/2010/04/spider.html
http://odokuchang.blogspot.jp/2012/04/mysqlspidersandboxsandbox.html

export SANDBOX_BINARY=$HOME/opt/mysql
export SANDBOX_HOME=$HOME/opt/sandboxes
 
mkdir ~/opt/mysql
cd ~/opt/mysql
 
ln -s /usr/local/mysql-5.5.14-spider 5.5.14
 
make_multiple_sandbox --how_many_nodes=4 5.5.14

cd ~/opt/sandboxes/multi_msb_5_5_14/
./use_all 'create database spider_test character set utf8'
cp /usr/local/mysql-5.5.14-spider/install_spider.sql .
./use_all 'source install_spider.sql'  

# 再起動
./stop_all
./start_all

# 各nodeのportを調査
./use_all 'select @@port'
# server: 1: 
@@port
13915
# server: 2: 
@@port
13916
# server: 3: 
@@port
13917
# server: 4: 
@@port
13918

# 各nodeの接続先を登録
# msandboxはmysql::sandboxのデフォルトユーザー名,パスワード
./use_all "CREATE SERVER n1 FOREIGN DATA WRAPPER mysql OPTIONS (USER 'root', PASSWORD '', HOST '127.0.0.1', PORT 3306);
CREATE SERVER n2 FOREIGN DATA WRAPPER mysql OPTIONS (USER 'msandbox', PASSWORD 'msandbox', HOST '127.0.0.1', PORT 13915);  
CREATE SERVER n3 FOREIGN DATA WRAPPER mysql OPTIONS (USER 'msandbox', PASSWORD 'msandbox', HOST '127.0.0.1', PORT 13916);  
CREATE SERVER n4 FOREIGN DATA WRAPPER mysql OPTIONS (USER 'msandbox', PASSWORD 'msandbox', HOST '127.0.0.1', PORT 13917);  
CREATE SERVER n5 FOREIGN DATA WRAPPER mysql OPTIONS (USER 'msandbox', PASSWORD 'msandbox', HOST '127.0.0.1', PORT 13918);"

# 消すときは
# ./use_all "drop server n1;drop server n2;drop server n3;drop server n4;drop server n5;"

# ※通常のmysqlクライアントで各sandboxに繋ぐのも、いつもと同じ要領
# mysql -umsandbox -pmsandbox -h 127.0.0.1 -P 13916


# 3306のmysqlにテーブルを作り、同時にspiderのマスターにする。
mysql -uroot -h localhost -P 3306
use spider_test;
CREATE TABLE salaries (
  emp_no int(11) NOT NULL,
  salary int(11) NOT NULL,
  from_date date NOT NULL,
  to_date date NOT NULL,
  PRIMARY KEY (emp_no)
) ENGINE=SPIDER DEFAULT CHARSET=utf8
PARTITION BY HASH(emp_no) (
  PARTITION p1 COMMENT 'user "msandbox", password "msandbox",  host "127.0.0.1", port "13915", table "salaries",',
  PARTITION p2 COMMENT 'user "msandbox", password "msandbox",  host "127.0.0.1", port "13916", table "salaries",',
  PARTITION p3 COMMENT 'user "msandbox", password "msandbox",  host "127.0.0.1", port "13917", table "salaries",',
  PARTITION p4 COMMENT 'user "msandbox", password "msandbox",  host "127.0.0.1", port "13918", table "salaries",'
);

# node1からnode4までにテーブルを作る
./use_all "
use spider_test;
CREATE TABLE salaries (
    emp_no int(11) NOT NULL,
    salary int(11) NOT NULL,
    from_date date NOT NULL,
    to_date date NOT NULL,
    PRIMARY KEY (emp_no)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;"

# 消す場合は
# ./use_all 'use spider_test; drop table salaries;'
# 3306にデータをinsert
mysql -uroot -h localhost -P 3306
use spider_test;
insert into salaries(emp_no, salary) values(1, 1000);
insert into salaries(emp_no, salary) values(2, 2000);
insert into salaries(emp_no, salary) values(3, 3000);


./use_all 'use spider_test;
select * from salaries;'
# server: 1: 
# server: 2: 
emp_no salary from_date to_date
1 1000 0000-00-00 0000-00-00
# server: 3: 
emp_no salary from_date to_date
2 2000 0000-00-00 0000-00-00
# server: 4: 
emp_no salary from_date to_date
3 3000 0000-00-00 0000-00-00

# node1から4に分散されてます。
# sandbox便利だのう。


■handlersocket経由でspiderを使ってみる

# ruby用のhandlersocketクライアントを入れる
cd /usr/src/HandlerSocket-Plugin-for-MySQL/
sudo wget https://bitbucket.org/winebarrel/ruby-handlersocket/get/tip.tar.gz
sudo tar zxvf tip.tar.gz
sudo mv winebarrel-ruby-handlersocket-c19841e47ea2/* .
sudo rm -r winebarrel-ruby-handlersocket-c19841e47ea2/
sudo ruby extconf.rb
sudo make
sudo make install


# spiderとhandlersocketを同時に利用できるように、設定を追加
# ここを参照
http://wild-growth-ja.blogspot.jp/2011/02/mysqlspidervpotherspider-224-vp-013.html

vi /etc/my.cnf
spider_use_hs_read=1
spider_use_hs_write=1

# 全部再起動
mysql.server restart
cd ~/opt/sandboxes
./start_all


■ruby -> spider(9999) -> sandbox spider-node へ接続
vi ahndler_sample.rb

require 'rubygems'
require 'handlersocket'
 
hs = HandlerSocket.new('127.0.0.1', 9999)
# Args (default value)
# host(localhost), port(9998), timeout(600), listen_backlog(256)
 
# 3は識別子
hs.open_index(3, 'spider_test', 'salaries', 'PRIMARY', 'emp_no,salary');
 
# select 接続、条件、条件値、count、offset
p res = hs.execute_single(3, '>=', [2], 100, 0);

 
hs.close

## エラーでとれない

ruby handler_sample.rb 
[-1, "read: eof"]

# しかも、mysqlがクラッシュ
tail /var/log/system.log
May  3 18:40:19 xxx-no-MacBook-Air librariand[356]: no ubiquity account configured, not creating collection
May  3 18:40:19 xxx-no-MacBook-Air librariand[356]: error in handle_client_request: LibrarianErrorDomain/10/Unable to configure the collection.

# 起動しようとするとエラー。
mysqld
120503 18:43:11 [Warning] Setting lower_case_table_names=2 because file system for /var/lib/mysql/data/ is case insensitive
120503 18:43:11 InnoDB: The InnoDB memory heap is disabled
120503 18:43:11 InnoDB: Mutexes and rw_locks use GCC atomic builtins
120503 18:43:11 InnoDB: Compressed tables use zlib 1.2.5
120503 18:43:11 InnoDB: Initializing buffer pool, size = 128.0M
120503 18:43:11 InnoDB: Completed initialization of buffer pool
120503 18:43:11 InnoDB: highest supported file format is Barracuda.
120503 18:43:11  InnoDB: Waiting for the background threads to start
120503 18:43:12 InnoDB: 1.1.8 started; log sequence number 1604997
[Warning] handlersocket: open_files_limit is too small.
[Warning] handlersocket: open_files_limit is too small.
120503 18:43:12 [Note] Recovering after a crash using tc.log
120503 18:43:12 - mysqld got signal 11 ;
This could be because you hit a bug. It is also possible that this binary
or one of the libraries it was linked against is corrupt, improperly built,
or misconfigured. This error can also be caused by malfunctioning hardware.
We will try our best to scrape up some info that will hopefully help diagnose
the problem, but since we have already crashed, something is definitely wrong
and this may fail.

key_buffer_size=16384
read_buffer_size=262144
max_used_connections=0
max_threads=151
thread_count=17
connection_count=0
It is possible that mysqld could use up to 
key_buffer_size + (read_buffer_size + sort_buffer_size)*max_threads = 50051 K
bytes of memory
Hope that's ok; if not, decrease some variables in the equation.

Thread pointer: 0x0
Attempting backtrace. You can use the following information to find out
where mysqld died. If you see no messages after this, something went
terribly wrong...
stack_bottom = 0x0 thread_stack 0x40000
0   mysqld                              0x00000001073c00fe my_print_stacktrace + 46
1   mysqld                              0x000000010720d13b handle_segfault + 523
2   libsystem_c.dylib                   0x00007fff87054cfa _sigtramp + 26
3   ???                                 0x00007fff66d47ae0 0x0 + 140734918589152
4   mysqld                              0x00000001071e43e5 _ZN11TC_LOG_MMAP4openEPKc + 1301
5   mysqld                              0x00000001072134a5 _Z11mysqld_mainiPPc + 10965
6   mysqld                              0x000000010714a7f4 start + 52
7   ???                                 0x0000000000000001 0x0 + 1

# あれ、そういえばhandlersocketのportは[9998-9999] なんだけど、
# sandbox使ってる場合、sandboxのmysqlのhandlersocketはどのportになるんだろう。
# しかも、handlersocket プラグインを各sandboxにinstallせねばならないのではなかろうか。
# spider-nodeがhandlersocket非対応ならsqlでデータ取得するというspiderの仕様だったと思うが、その動きは見られず。



■sandboxを1台に変更する
ruby -> spider(9997) -> sandbox spider-node(9999) へ接続

# spiderからsandboxのspider-nodeにhandlersocketでアクセスする際の設定を変更したいけど、
# spider -> sandboxへのアクセスでのport指定をどこでやればよいのか見つからないため、sandboxを1台に変更する。(デフォルトの9999で繋いでくれるかな。)

# 1台のsandboxを再定義
cd ~/opt/mysql
make_multiple_sandbox --how_many_nodes=1 5.5.14

cd ~/opt/sandboxes/multi_msb_5_5_14/
./use_all 'create database spider_test character set utf8'
cp /usr/local/mysql-5.5.14-spider/install_spider.sql .
./use_all 'source install_spider.sql'  


# 再起動
./stop_all
./start_all

# handlersocket
./n1
install plugin handlersocket soname 'handlersocket.so';

vi node1/my.sandbox.cnf
[mysqld]
handlersocket_port = 9998
handlersocket_port_wr = 9999
handlersocket_address =
handlersocket_verbose = 0
handlersocket_timeout = 300
handlersocket_threads = 16
thread_concurrency = 128
open_files_limit = 65535

spider_internal_xa=1
spider_semi_trx_isolation=2
spider_use_handler=1
spider_use_hs_read=1
spider_use_hs_write=1

# 各nodeのportを調査
./use_all 'select @@port'
# server: 1: 
@@port
13915

# 各nodeの接続先を登録
# msandboxはmysql::sandboxのデフォルトユーザー名,パスワード
./use_all "CREATE SERVER n1 FOREIGN DATA WRAPPER mysql OPTIONS (USER 'root', PASSWORD '', HOST '127.0.0.1', PORT 3306);
CREATE SERVER n2 FOREIGN DATA WRAPPER mysql OPTIONS (USER 'msandbox', PASSWORD 'msandbox', HOST '127.0.0.1', PORT 13915);"

# ※通常のmysqlクライアントで各sandboxに繋ぐのも、いつもと同じ要領
# mysql -umsandbox -pmsandbox -h 127.0.0.1 -P 13916


# 3306のmysqlにテーブルを作り、同時にspiderのマスターにする。
mysql -uroot -h localhost -P 3306
use spider_test;
CREATE TABLE salaries (
  emp_no int(11) NOT NULL,
  salary int(11) NOT NULL,
  from_date date NOT NULL,
  to_date date NOT NULL,
  PRIMARY KEY (emp_no)
) ENGINE=SPIDER DEFAULT CHARSET=utf8
PARTITION BY HASH(emp_no) (
  PARTITION p1 COMMENT 'user "msandbox", password "msandbox",  host "127.0.0.1", port "13915", table "salaries",'
);

# node1にテーブルを作る
./use_all "
use spider_test;
CREATE TABLE salaries (
    emp_no int(11) NOT NULL,
    salary int(11) NOT NULL,
    from_date date NOT NULL,
    to_date date NOT NULL,
    PRIMARY KEY (emp_no)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;"

# spiderのhandlersocketのportを変更する。
vi /etc/my.cnf
[mysqld]
handlersocket_port = 9996
handlersocket_port_wr = 9997

mysql.server restart
cd ~/opt/sandboxes/
./restart_all


■実際にhandlersocketで接続
handler_sample1.rb

require 'rubygems'
require 'handlersocket'

# spider経由
hs = HandlerSocket.new('127.0.0.1', 9997)
# 直接sandbox
#hs = HandlerSocket.new('127.0.0.1', 9999)
# Args (default value)
# host(localhost), port(9998), timeout(600), listen_backlog(256)
 
# 3は識別子
hs.open_index(3, 'spider_test', 'salaries', 'PRIMARY', 'emp_no,salary');
 
# select 接続、条件、条件値、count、offset
p res = hs.execute_single(3, '>=', [2], 100, 0);
 
# insert 接続、行
hs.execute_insert(3, [1,"10000"]);
hs.execute_insert(3, [2,"20000"]);
hs.execute_insert(3, [3,"30000"]);
 
# delete 接続、条件、条件値、count、offset ← selectして消すため
# 詳細はここ
# https://github.com/ahiguti/HandlerSocket-Plugin-for-MySQL/blob/master/docs-ja/perl-client.ja.txt
hs.execute_delete(3, '=', [2], 1, 0);
 
# 高速なexecute_multi
p hs.execute_multi(
  [
    [3, '=', [3], 1, 0],
    [3, '=', [1], 1, 0]
  ]
)
 
hs.close


■実行結果

# port 9997(spider)だとエラー
# ruby -> spider -> sandbox
ruby handler_sample1.rb 
[-1, "read: eof"]
[[-1, "read: eof"]]


# port 9999(spider-node)だととれる
# ruby -> sandbox
ruby handler_sample1.rb 
[0, "3", "3000"]
[[0, "3", "3000"], [0, "1", "1000"]]

なんでやねん!! documentのspider_use_hs_writeオプションの項に下のように書いてあるけど、handlersocketを別で入れたから駄目なのかな。 「このオプションは、handlersocket用パッチ適用済みバイナリでのみ利用可能。」 今日はここまで。。

2012年4月30日月曜日

MacのMySQLでHandlerSocketのベンチマークをとった

インストールはこちらを参照
MacにMySQL(5.5系)とHandlerSocketをいれた


■前提として、1台のmacで行っているため、スケールアウトのメリットを享受できていません。
そのため、Cassandra やhbaseでは期待する効果が出ていません!!
# cassandra のキースペースを作る
cassandra-cli
[default@unknown] create keyspace Test;
[default@unknown] use Test;
[default@Test] create column family Users with column_type = 'Standard' and comparator = 'UTF8Type';
bench.rb

#!/usr/bin/ruby
# -*- encoding: utf-8 -*-
require 'rubygems'
require 'cassandra'
require 'active_record'
require 'benchmark'
require 'handlersocket'
require 'memcache'

# ---------------------------------------
# init
# ---------------------------------------
# mysql :
#   mysql
#   use Test; truncate table user;
# memcacha :
#   ps aux | grep mem
#   kill -TERM xxxx
#   memcached -d
# cassandra 
#   cassandra-cli
#   use Test;
#   truncate Users;


# ---------------------------------------
# Insert / Select 性能
# ---------------------------------------
count = 100000
p 'count:' + count.to_s

# ---------------------------------------
# mysql
ActiveRecord::Base.establish_connection(
  :adapter => 'mysql2',
  :host => 'localhost',
  :username => 'root',
  :password => '',
  :database => 'test'
)
class User < ActiveRecord::Base
  self.table_name = 'user'
end

# active record 利用
Benchmark.bm { |rep|
  rep.report("mysql(o/r) insert ") {
    for num in 1..count
      name = 'name' + num.to_s
      User.create(:name => name)
    end
  }
}
Benchmark.bm { |rep|
  rep.report("mysql(o/r) select") {
    for num in 1..count
      id = rand(count).to_i + 1
      User.find(id)
    end
  }
}
# すべて削除
User.connection.execute('truncate table user')

# SQL利用
Benchmark.bm { |rep|
  rep.report("mysql(sql) insert ") {
    for num in 1..count
      name = 'name' + num.to_s
      User.connection.execute(sprintf('insert into user (user_id, name) values(%s, "%s");', num.to_s, name))
    end
  }
}
Benchmark.bm { |rep|
  rep.report("mysql(sql) select") {
    for num in 1..count
      id = rand(count).to_i + 1
      User.connection.execute(sprintf('select user_id, name from user where user_id = %s;', num.to_s))
    end
  }
}
# すべて削除
User.connection.execute('truncate table user')


# ---------------------------------------
# cassandra
include Cassandra::Constants
client = Cassandra.new("Test", "127.0.0.1:9160")
Benchmark.bm { |rep|
  rep.report("cassandra insert ") {
    for num in 1..count
      name = 'name' + num.to_s
      client.insert(:Users, num.to_s, { 'name' => name } )
    end
  }
}
Benchmark.bm { |rep|
  rep.report("cassandra select ") {
    for num in 1..count
      id = rand(count).to_i + 1
      client.get(:Users, id.to_s)
    end
  }
}

# ---------------------------------------
# memcached
cache = MemCache.new('localhost:11211')
Benchmark.bm { |rep|
  rep.report("memcache insert ") {
    for num in 1..count
      name = 'name' + num.to_s
      cache[name] = [num, name]
    end
  }
}
Benchmark.bm { |rep|
  rep.report("memcache select ") {
    for num in 1..count
      id = rand(count).to_i + 1
      name = 'name' + id.to_s
      ret = cache[name]
    end
  }
}

# ---------------------------------------
# handlersocket
hs = HandlerSocket.new('127.0.0.1', 9999)
hs.open_index(3, 'test', 'user', 'PRIMARY', 'user_id,name');

Benchmark.bm { |rep|
  rep.report("handlersocket insert ") {
    for num in 1..count
      name = 'name' + num.to_s
      hs.execute_insert(3, [num, name]);
    end
  }
}
Benchmark.bm { |rep|
  rep.report("handlersocket select ") {
    for num in 1..count
      id = rand(count).to_i + 1
      ret = hs.execute_single(3, '=', [id], 1, 0);
    end
  }
}





100,000件で試験
mysql, cassandraはtruncate後
memcacheは再起動後
ruby bench.rb 

・1回目
"count:100000"
      user     system      total        real
mysql(o/r) insert  74.320000   5.670000  79.990000 (110.039184)
      user     system      total        real
mysql(o/r) select 50.610000   2.650000  53.260000 ( 65.465168)
      user     system      total        real
mysql(sql) insert   4.430000   1.530000   5.960000 ( 29.590552)
      user     system      total        real
mysql(sql) select  5.470000   1.780000   7.250000 ( 13.550391)
      user     system      total        real
cassandra insert  47.180000   3.140000  50.320000 ( 61.347904)
      user     system      total        real
cassandra select  69.150000   3.470000  72.620000 (111.568860)
      user     system      total        real
memcache insert  14.930000   2.280000  17.210000 ( 17.935214)
      user     system      total        real
memcache select  16.710000   2.080000  18.790000 ( 19.264883)
      user     system      total        real
handlersocket insert   1.430000   1.510000   2.940000 ( 26.721995)
      user     system      total        real
handlersocket select   1.320000   1.520000   2.840000 (  7.867557)


・2回目
"count:100000"
      user     system      total        real
mysql(o/r) insert  74.500000   5.680000  80.180000 (110.519581)
      user     system      total        real
mysql(o/r) select 48.570000   2.550000  51.120000 ( 63.455239)
      user     system      total        real
mysql(sql) insert   4.420000   1.510000   5.930000 ( 29.494878)
      user     system      total        real
mysql(sql) select  5.500000   1.800000   7.300000 ( 13.632243)
      user     system      total        real
cassandra insert  45.500000   3.130000  48.630000 ( 59.691931)
      user     system      total        real
cassandra select  66.840000   3.350000  70.190000 (108.169329)
      user     system      total        real
memcache set  14.870000   2.340000  17.210000 ( 17.894275)
      user     system      total        real
memcache get  17.220000   2.260000  19.480000 ( 20.023089)
      user     system      total        real
handlersocket insert   1.490000   1.540000   3.030000 ( 26.834126)
      user     system      total        real
handlersocket select   1.310000   1.520000   2.830000 (  7.845230)

# 前提として、1台のmacで行っているため、スケールアウトのメリットを享受できていません。
# そのため、Cassandra やhbaseでは期待する効果が出ていません!!

# Cassandraは1台だとパフォーマンスでないな。
# やっぱO/Rも重い。
# memcacheのsystem時間がたくさんかかってるのはなんでだろう。localhostだと重いのかな。



# 条件
# mac book air OSX
# 1.7GHz Intel Core i5
# 4GB 1333 MHz DDR3

mysql --version
mysql  Ver 14.14 Distrib 5.5.20, for osx10.7 (i386) using readline 5.1

cassandra -v
1.1.0

telnet localhost 11211
stats
STAT version 1.4.5 ←memcachedのバージョン

HandlerSocket-Plugin-for-MySQL
1.1.0

MacにMySQL(5.5系)とHandlerSocketをいれた


# mysqlをインストール
# 既にインストール済みなら同じverのソースを持ってくる
brew install mysql

# ここを参考に。
http://www.bigegg.net/post/4651592197/handlersocket-osx

cp /Library/Caches/Homebrew/mysql-5.5.20.tar.gz .
tar zxvf mysql-5.5.20.tar.gz 
cd mysql-5.5.20
# configure.cmakeにバグがあるので、下記をみて修正。
http://bugs.mysql.com/bug.php?id=65050
cmake .

# 起動するも失敗
mysql.server start
ERROR! The server quit without updating PID file (…)

# conf
cp /usr/local/Cellar/mysql/5.5.20/support-files/my-small.cnf /etc/my.cnf 

mysql_install_db --verbose --user=`whoami` --basedir=/usr/local/Cellar/mysql/5.5.20 --datadir=/usr/local/var/mysql

# 再度起動
mysql.server start
Starting MySQL
.. SUCCESS! 

# handler socketをインストール
# ここを参考に。
https://github.com/ahiguti/HandlerSocket-Plugin-for-MySQL

git clone git://github.com/ahiguti/HandlerSocket-Plugin-for-MySQL.git
cd HandlerSocket-Plugin-for-MySQL/

./autogen.sh
./configure --with-mysql-source=/Users/xxx/src/mysql-5.5.20(mysqlソースパス) --with-mysql-bindir=/usr/local/Cellar/mysql/5.5.20/bin/(mysqlコマンドのパス)  --with-mysql-plugindir=/usr/local/Cellar/mysql/5.5.20/lib/plugin
make
make install

# 別コンソールでmysqlを起動し、
mysql> install plugin handlersocket soname 'handlersocket.so';

# プラグインが入ったかな。
ls /usr/local/Cellar/mysql/5.5.20/lib/plugin/

# handlersocketの設定を入れる。
sudo vi /etc/my.cnf 
handlersocket_port = 9998
handlersocket_port_wr = 9999
handlersocket_address =
handlersocket_verbose = 0
handlersocket_timeout = 300
handlersocket_threads = 16
thread_concurrency = 128
open_files_limit = 65535

# mysql再起動
mysql.server stop
Shutting down MySQL
. SUCCESS! 
mysql.server start
Starting MySQL
.. SUCCESS! 


# 別コンソールでmysqlを起動し、
mysql> show plugins;
+-----------------------+--------+--------------------+------------------+---------+
| Name                  | Status | Type               | Library          | License |
+-----------------------+--------+--------------------+------------------+---------+
| binlog                | ACTIVE | STORAGE ENGINE     | NULL             | GPL     |
| mysql_native_password | ACTIVE | AUTHENTICATION     | NULL             | GPL     |
| mysql_old_password    | ACTIVE | AUTHENTICATION     | NULL             | GPL     |
| CSV                   | ACTIVE | STORAGE ENGINE     | NULL             | GPL     |
| MEMORY                | ACTIVE | STORAGE ENGINE     | NULL             | GPL     |
| MyISAM                | ACTIVE | STORAGE ENGINE     | NULL             | GPL     |
| MRG_MYISAM            | ACTIVE | STORAGE ENGINE     | NULL             | GPL     |
| InnoDB                | ACTIVE | STORAGE ENGINE     | NULL             | GPL     |
| INNODB_TRX            | ACTIVE | INFORMATION SCHEMA | NULL             | GPL     |
| INNODB_LOCKS          | ACTIVE | INFORMATION SCHEMA | NULL             | GPL     |
| INNODB_LOCK_WAITS     | ACTIVE | INFORMATION SCHEMA | NULL             | GPL     |
| INNODB_CMP            | ACTIVE | INFORMATION SCHEMA | NULL             | GPL     |
| INNODB_CMP_RESET      | ACTIVE | INFORMATION SCHEMA | NULL             | GPL     |
| INNODB_CMPMEM         | ACTIVE | INFORMATION SCHEMA | NULL             | GPL     |
| INNODB_CMPMEM_RESET   | ACTIVE | INFORMATION SCHEMA | NULL             | GPL     |
| PERFORMANCE_SCHEMA    | ACTIVE | STORAGE ENGINE     | NULL             | GPL     |
| partition             | ACTIVE | STORAGE ENGINE     | NULL             | GPL     |
| handlersocket         | ACTIVE | DAEMON             | handlersocket.so | BSD     |
+-----------------------+--------+--------------------+------------------+---------+
18 rows in set (0.00 sec)

# 入った!!


# 使ってみる
use test;
CREATE TABLE `user` (
    `user_id` INT(10) NOT NULL AUTO_INCREMENT,
    `name` VARCHAR(255) NULL DEFAULT NULL,
    `birthday` DATE NULL DEFAULT NULL,
    `memo` VARCHAR(255) NULL DEFAULT NULL,
    PRIMARY KEY (`user_id`)
);



# ruby用クライアントを入れる
# tarはここからダウンロード
https://bitbucket.org/winebarrel/ruby-handlersocket/src


cd HandlerSocket-Plugin-for-MySQL/ ←ここでmakeせねばならん。
tar zxvf winebarrel-ruby-handlersocket-c19841e47ea2.tar.gz 
cp winebarrel-ruby-handlersocket-c19841e47ea2/* .
ruby extconf.rb
make
make install

# ------------------------------------
# sample.rb
require 'handlersocket'

hs = HandlerSocket.new('127.0.0.1', 9999)
# Args (default value)
# host(localhost), port(9998), timeout(600), listen_backlog(256)

# 3は識別子
hs.open_index(3, 'test', 'user', 'PRIMARY', 'user_id,name,birthday,memo');

# select 接続、条件、条件値、count、offset
p res = hs.execute_single(3, '>=', ['2'], 100, 0);

# insert 接続、行
hs.execute_insert(3, [1,"name1","2001-01-01","memo1"]);
hs.execute_insert(3, [2,"name2","2001-01-01","memo2"]);
hs.execute_insert(3, [3,"name3","2001-01-01","memo3"]);

# delete 接続、条件、条件値、count、offset ← selectして消すため
# 詳細はここ
# https://github.com/ahiguti/HandlerSocket-Plugin-for-MySQL/blob/master/docs-ja/perl-client.ja.txt
hs.execute_delete(3, '=', ['2'], 1, 0);

# 高速なexecute_multi
p hs.execute_multi(
  [
    [3, '=', ['3'], 1, 0],
    [3, '=', ['1'], 1, 0]
  ]
)

hs.close




# ------------------------------------
sample.rb

require 'handlersocket'

hs = HandlerSocket.new('127.0.0.1', 9999)
# Args (default value)
# host(localhost), port(9998), timeout(600), listen_backlog(256)

# 3は識別子
hs.open_index(3, 'test', 'user', 'PRIMARY', 'user_id,name,birthday,memo');

# select 接続、条件、条件値、count、offset
p res = hs.execute_single(3, '>=', ['2'], 100, 0);

# insert 接続、行
hs.execute_insert(3, [1,"name1","2001-01-01","memo1"]);
hs.execute_insert(3, [2,"name2","2001-01-01","memo2"]);
hs.execute_insert(3, [3,"name3","2001-01-01","memo3"]);

# delete 接続、条件、条件値、count、offset ← selectして消すため
# 詳細はここ
# https://github.com/ahiguti/HandlerSocket-Plugin-for-MySQL/blob/master/docs-ja/perl-client.ja.txt
hs.execute_delete(3, '=', ['2'], 1, 0);

# 高速なexecute_multi
p hs.execute_multi(
  [
    [3, '=', ['3'], 1, 0],
    [3, '=', ['1'], 1, 0]
  ]
)

hs.close
次回はこちら
MacのMySQLでHandlerSocketのベンチマークをとった