see http://d.hatena.ne.jp/spiritloose/20080327、http://blog.livedoor.jp/sasata299/archives/51280681.html
CREATE TABLE sequence (id INT UNSIGNED NOT NULL) ENGINE=InnoDB; INSERT INTO sequence VALUES (100); CREATE TABLE hoge ( id INT UNSIGNED NOT NULL PRIMARY KEY DEFAULT 0, content TEXT ) ENGINE=MyISAM; DROP TRIGGER IF EXISTS hoge_set_id; delimiter // CREATE TRIGGER hoge_set_id BEFORE INSERT ON hoge FOR EACH ROW BEGIN UPDATE sequence SET id = LAST_INSERT_ID(id + 1000); SET NEW.id = LAST_INSERT_ID(); END; // delimiter ;
EC2で別のインスタンスを5つほど立ち上げて、以下のスクリプトをそれぞれで実行。
require 'rubygems' require 'mysql' HOST = 'XXX.compute.amazonaws.com' USER = 'scott' PASS = 'XXX' DB = 'sandbox' begin my = Mysql.new(HOST, USER, PASS, DB) 100000.times do my.query("INSERT INTO hoge (content) VALUES ('hoge')"); end ensure my.close if my end
30分で50万件だから、277qpsか…おっせー。
[root@ip-XXX-XXX-XXX-XXX ~]# time ruby test.rbreal 29m58.939s
user 0m0.044s
sys 0m0.068s
ボトルネックになってるのかも。
比較用に普通にauto_incrementを使ってみる。
DROP TABLE IF EXISTS hoge; CREATE TABLE hoge ( id INT UNSIGNED NOT NULL PRIMARY KEY auto_increment, content TEXT ) ENGINE=MyISAM; DROP TRIGGER IF EXISTS hoge_set_id;
ええええええぇぇぇぇぇぇぇぇぇぇぇぇぇぇぇぇ…
[root@ip-XXX-XXX-XXX-XXX ~]# time ruby test.rbreal 1m27.934s
user 0m0.048s
sys 0m0.068s
sequenceをMEMORYにしてみよう…
DROP TABLE IF EXISTS sequence; CREATE TABLE sequence (id INT UNSIGNED NOT NULL) ENGINE=MEMORY; INSERT INTO sequence VALUES (100);
今度は同じくらい。
[root@ip-XXX-XXX-XXX-XXX ~]# time ruby test.rbreal 1m46.856s
user 0m0.056s
sys 0m0.060s
ついでにMyISAMも調べる。
ふむふむ。
[root@ip-XXX-XXX-XXX-XXX ~]# time ruby test.rbreal 2m2.846s
user 0m0.040s
sys 0m0.068s
NDBとかだとさらに遅いんだろうか?