複数キーの INDEX を追加する

いろいろ中途半端なのは十分認識しているけど「Rails レシピブック」読んでたら Rails アプリを作りたくなってきた。のでやる(笑)

model を作る

 > ruby script/generate model schedule

migrate ファイルを修正する

  • db/migrate/001_create_schedule.rb
class CreateSchedules < ActiveRecord::Migration
  def self.up
    create_table :schedules do |t|
      t.string :username, :null => false
      t.date :date, :null => false
      t.text :text

      t.timestamps
    end
    add_index :schedules, [:username, :date]
  end

  def self.down
    drop_table :schedules
  end
end

INDEX を複数キーで登録する場合は配列で指定

add_index :schedules, [:username, :date]

テーブルを作る

rake db:migrate

テーブルができているか確認する

mysql を使っているのでコマンドを実行

mysql> show tables;
+----------------------+
| Tables_in_schedutter |
+----------------------+
| schedules            | 
| schema_info          | 
+----------------------+
3 rows in set (0.00 sec)

テーブル定義を見てみる

mysql> desc schedules;
+------------+--------------+------+-----+
| Field      | Type         | Null | Key |
+------------+--------------+------+-----+
| id         | int(11)      | NO   | PRI |
| username   | varchar(255) | NO   | MUL |
| date       | date         | NO   |     |
| text       | text         | YES  |     |
| created_at | datetime     | YES  |     |
| updated_at | datetime     | YES  |     |
+------------+--------------+------+-----+

---------+----------------+
 Default | Extra          |
---------+----------------+
 NULL    | auto_increment | 
         |                | 
         |                | 
 NULL    |                | 
 NULL    |                | 
 NULL    |                | 
---------+----------------+

6 rows in set (0.01 sec)

複数キーで定義すると Key に MUL が入るらしい。

INDEX 定義を見てみる

mysql> show index from schedules;
+-----------+------------+--------------------------------------+
| Table     | Non_unique | Key_name                             |
+-----------+------------+--------------------------------------+
| schedules |          0 | PRIMARY                              |
| schedules |          1 | index_schedules_on_username_and_date |
| schedules |          1 | index_schedules_on_username_and_date |
+-----------+------------+--------------------------------------+

--------------+-------------+
 Seq_in_index | Column_name |
--------------+-------------+
            1 | id          |
            1 | username    |
            2 | date        |
--------------+-------------+

3 rows in set (0.00 sec)

表示しきれないので一部だけ。
index_schedules_on_username_and_date と言う名前で INDEX が生成されていることが分かる。

INDEX を使った検索が行われるかを確認する。

mysql> explain select * from schedules where username='spider-man' and date='20080614';
+----+-------------+-----------+------+
| id | select_type | table     | type |
+----+-------------+-----------+------+
|  1 | SIMPLE      | schedules | ref  |
+----+-------------+-----------+------+

--------------------------------------+
 possible_keys                        |
--------------------------------------+
 index_schedules_on_username_and_date |
--------------------------------------+

--------------------------------------+
 key                                  |
--------------------------------------+
 index_schedules_on_username_and_date |
--------------------------------------+

---------+-------------+------+-------------+
 key_len | ref         | rows | Extra       |
---------+-------------+------+-------------+
 770     | const,const |    1 | Using where | 
---------+-------------+------+-------------+

1 row in set (0.00 sec)

使用された INDEX が表示される。
ためしに INDEX を使わない検索をしてみる。

mysql> explain select * from schedules where text='';
+----+-------------+-----------+------+---------------+
| id | select_type | table     | type | possible_keys |
+----+-------------+-----------+------+---------------+
|  1 | SIMPLE      | schedules | ALL  | NULL          |
+----+-------------+-----------+------+---------------+

------+---------+------+------+-------------+
 key  | key_len | ref  | rows | Extra       |
------+---------+------+------+-------------+
 NULL | NULL    | NULL |    1 | Using where | 
------+---------+------+------+-------------+

1 row in set (0.00 sec)

INDEX が表示されていないので、INDEX が使われて居ないことがわかる。