複数列indexの順序を決める時にどういう順番で並べますかっていうと
選択性の高い列から並べるのが原則
それじゃ、最近のDBでセオリー通りのindexとそうじゃない順序のindexでどれくらい差が出るもんなの、というのを単純なケースで試してみる
DB:MariaDB 10.0.11
OS:Ubuntu 14.04
マシン:thinkpad t440p(ssd)
#テーブルとindex
テーブルとテストは前回も使用したのを流用する
http://qiita.com/k_o_gj/items/a663692c3389ec7cc29d
CREATE TABLE event_test(
id BIGINT AUTO_INCREMENT,
event_id INT NOT NULL DEFAULT 0,
user_id INT NOT NULL DEFAULT 0,
status INT NOT NULL DEFAULT 0,
create_time DATETIME NOT NULL,
update_time DATETIME NOT NULL,
delete_time DATETIME NOT NULL,
PRIMARY KEY (id),
KEY (user_id,event_id)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
例えば以下のようなクエリを出すとすると、user_idにマッチする行のほうが少ないのでuser_idがindex順序の先にくるべきということになる
select * from event_test where event_id = 4 AND user_id = 38651;
MariaDB [my_test]> select sum(event_id = 4), sum(user_id = 38651) from event_test\G
*************************** 1. row ***************************
sum(event_id = 4): 2309567
sum(user_id = 38651): 12
1 row in set (8.30 sec)
table全体でみてもuser_idのほうが選択性が高いのでindex順序は(user_id,event_id)のほうが(event_id,user_id)よりgoodということになる
MariaDB [my_test]> select count(distinct event_id)/count(*) AS eid_selectivity, count(distinct user_id)/count(*) AS uid_selectivity, count(*) from event_test\G
*************************** 1. row ***************************
eid_selectivity: 0.0000
uid_selectivity: 0.0866
count(*): 34623542
1 row in set (11.68 sec)
#テスト
テストはsysbenchのselect.luaのevent関数を以下のようにちょっと変更して実行
4スレッドで5分間軽い検索をし続ける
function event(thread_id)
local eid
eid = sb_rand(0, 1000000)%15
rs = db_query("SELECT * FROM event_test WHERE event_id=" .. eid .. " AND user_id=" .. sb_rand(0,3000000))
end
./bin/sysbench --test=/tests/db/my_select_test.lua --db-driver=mysql --mysql-user=user --mysql-password=pass --mysql-host=127.0.0.1 --mysql-db=my_test --mysql-table-engine=innodb --num-threads=4 --max-requests=0 --max-time=300 run
#結果1
Running the test with following options:
Number of threads: 4
Random number generator seed is 0 and will be ignored
Threads started!
OLTP test statistics:
queries performed:
read: 10064763
write: 0
other: 0
total: 10064763
transactions: 0 (0.00 per sec.)
deadlocks: 0 (0.00 per sec.)
read/write requests: 10064763 (33549.20 per sec.)
other operations: 0 (0.00 per sec.)
General statistics:
total time: 300.0001s
total number of events: 10064763
total time taken by event execution: 1188.5505s
response time:
min: 0.07ms
avg: 0.12ms
max: 16.24ms
approx. 95 percentile: 0.14ms
Threads fairness:
events (avg/stddev): 2516190.7500/6959.39
execution time (avg/stddev): 297.1376/0.01
#結果2(indexを入れ替えて試す)
KEY (user_id, event_id)をKEY (event_id,user_id)に変更して実行
Running the test with following options:
Number of threads: 4
Random number generator seed is 0 and will be ignored
Threads started!
OLTP test statistics:
queries performed:
read: 9831949
write: 0
other: 0
total: 9831949
transactions: 0 (0.00 per sec.)
deadlocks: 0 (0.00 per sec.)
read/write requests: 9831949 (32772.17 per sec.)
other operations: 0 (0.00 per sec.)
General statistics:
total time: 300.0091s
total number of events: 9831949
total time taken by event execution: 1188.7031s
response time:
min: 0.07ms
avg: 0.12ms
max: 54.46ms
approx. 95 percentile: 0.14ms
Threads fairness:
events (avg/stddev): 2457987.2500/5045.16
execution time (avg/stddev): 297.1758/0.01
目を見張るほどの差異はない
単純なケースにおいては順序が実行結果に影響してくることはなさそう