2013-05-12 66 views
0

比方说,我有以下MySQL表:一个表中的两个索引,是仅在where子句中使用的第二个索引值得吗?

CREATE TABLE player (
    id int(9) unsigned NOT NULL DEFAULT 0 , 
    score MEDIUMINT(8) unsigned NOT NULL DEFAULT 0, 
    signupdate DATE NOT NULL, 
    lastupdate DATE NOT NULL 
) DEFAULT CHARACTER SET utf8 ENGINE=InnoDB; 

目前我有id列主键。 lastupdate列每天更新一次,如果未更新则表示玩家已删除该帐户,这意味着该列的可卡因性非常低。 也有一个关系表与精密组件相匹配matchidplayeridmatchdate

我的大部分查询都像

SELECT id,score,signupdate FROM player 
JOIN matches ON matches.playerid = player.id 
WHERE lastupdate = '{today}' 

所以3箱指数来我的心

  1. 的ID PRIMARY KEY
  2. ID和主键在lastupdate上的主键
  3. PRIMARY KEY on(id,lastupdate)

哪一个会是最好的?

+0

,主键定义行的唯一性。 ID本身应该是主键,因为它本身是唯一的。然后,如果你在'lastupdate'上添加一个,mysql可能*能够计算你的索引的合并优化。 – Sebas 2013-05-12 12:47:20

+0

数字3意味着你可以有许多用户使用相同的ID:每个lastupdate一个。所以3号不是一个不好的解决方案,但根本没有解决方案,因为它改变了数据库的行为。使用主键(id),您将拥有一个唯一的ID,使用(id,last_updated)您将没有唯一的ID。 – flaschenpost 2013-05-12 12:54:53

回答

1

您应该在表matchesplayerid上的索引以及表playerlastupdate上的索引。

作为一个非常粗略的经验法则,如果它是一个大型表,那么在WHEREJOIN子句中使用的应该有一个索引。

要获得更多信息,可以使用explain声明。这是它的样子。注意explain声明在最后:

mysql> CREATE TABLE player (
    ->  id int(9) unsigned NOT NULL DEFAULT 0 , 
    ->  score MEDIUMINT(8) unsigned NOT NULL DEFAULT 0, 
    ->  signupdate DATE NOT NULL, 
    ->  lastupdate DATE NOT NULL 
    ->) DEFAULT CHARACTER SET utf8 ENGINE=InnoDB; 
Query OK, 0 rows affected (0.12 sec) 

mysql> 
mysql> CREATE TABLE matches (
    ->  matchid int(9) unsigned NOT NULL DEFAULT 0 , 
    ->  playerid int(9) unsigned NOT NULL DEFAULT 0 , 
    ->  matchdate DATE NOT NULL 
    ->) DEFAULT CHARACTER SET utf8 ENGINE=InnoDB; 
Query OK, 0 rows affected (0.22 sec) 

mysql> 
mysql> SELECT id,score,signupdate FROM player 
    -> JOIN matches ON matches.playerid = player.id 
    -> WHERE lastupdate = now() 
    -> ; 
Empty set (0.00 sec) 

mysql> 
mysql> explain 
    -> SELECT id,score,signupdate FROM player 
    -> JOIN matches ON matches.playerid = player.id 
    -> WHERE lastupdate = '{today}' 
    -> ; 
+----+-------------+---------+------+---------------+------+---------+------+------+--------------------------------+ 
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra       | 
+----+-------------+---------+------+---------------+------+---------+------+------+--------------------------------+ 
| 1 | SIMPLE  | player | ALL | NULL   | NULL | NULL | NULL | 1 | Using where     | 
| 1 | SIMPLE  | matches | ALL | NULL   | NULL | NULL | NULL | 1 | Using where; Using join buffer | 
+----+-------------+---------+------+---------------+------+---------+------+------+--------------------------------+ 
2 rows in set, 2 warnings (0.00 sec) 

mysql> CREATE INDEX player_idx_1 
    -> ON player (id) 
    -> ; 
Query OK, 0 rows affected (0.15 sec) 
Records: 0 Duplicates: 0 Warnings: 0 

mysql> CREATE INDEX matches_idx_1 
    -> ON matches (playerid) 
    -> ; 
Query OK, 0 rows affected (0.16 sec) 
Records: 0 Duplicates: 0 Warnings: 0 

mysql> 
mysql> explain SELECT id,score,signupdate FROM player JOIN matches ON matches.playerid = player.id WHERE lastupdate = '{today}'; 
+----+-------------+---------+------+---------------+---------------+---------+-----------------+------+-------------+ 
| id | select_type | table | type | possible_keys | key   | key_len | ref    | rows | Extra  | 
+----+-------------+---------+------+---------------+---------------+---------+-----------------+------+-------------+ 
| 1 | SIMPLE  | player | ALL | player_idx_1 | NULL   | NULL | NULL   | 1 | Using where | 
| 1 | SIMPLE  | matches | ref | matches_idx_1 | matches_idx_1 | 4  | mysql.player.id | 1 | Using index | 
+----+-------------+---------+------+---------------+---------------+---------+-----------------+------+-------------+ 
2 rows in set, 2 warnings (0.00 sec) 

mysql> 

定义添加索引lastupdate

mysql> CREATE INDEX player_idx_2 
    -> ON player (lastupdate) 
    -> ; 
Query OK, 0 rows affected (0.13 sec) 
Records: 0 Duplicates: 0 Warnings: 0 
mysql> explain 
    -> SELECT id,score,signupdate FROM player 
    -> JOIN matches ON matches.playerid = player.id 
    -> WHERE lastupdate = curdate() 
    -> ; 
+----+-------------+---------+------+---------------+---------------+---------+-----------------+------+-------------+ 
| id | select_type | table | type | possible_keys | key   | key_len | ref    | rows | Extra  | 
+----+-------------+---------+------+---------------+---------------+---------+-----------------+------+-------------+ 
| 1 | SIMPLE  | player | ref | player_idx_2 | player_idx_2 | 3  | const   | 1 |    | 
| 1 | SIMPLE  | matches | ref | matches_idx_1 | matches_idx_1 | 4  | mysql.player.id | 1 | Using index | 
+----+-------------+---------+------+---------------+---------------+---------+-----------------+------+-------------+ 
2 rows in set (0.00 sec) 

mysql> 
+0

但是,mysql不是每个查询只使用一个索引?我在某处读过。 – 2013-05-12 12:06:57

+0

是的,它只需要一个。它需要'lastupdate',另一个不在你显示的查询中使用('SELECT id,score,signupdate FROM player WHERE lastupdate ='{today}'')。在'id'的另一个查询中,它可以使用主键索引。为什么否则,如果没有机会选择一个或另一个,你能够定义几个指标? – hol 2013-05-12 12:18:16

+0

更新了我的问题,很明显我使用player.id,加入了 – 2013-05-12 12:42:16

0

绝对数字2.主键用于唯一标识一行,并且id属性足够用于该属性,因此您不需要选项3.并且由于大多数查询看起来像您所说的,因此有lastupdate上的索引对于加快您的查询速度绝对有用。

+0

但是dosent mysql每个查询只使用一个索引? – 2013-05-12 12:04:15

+0

你可以看一下MySQL手册:dev.mysql.com/doc/refman/5.0/en/mysql-indexes.html – Juampi 2013-05-12 12:10:13

+0

每个表只查询一个索引,所以'lastupdate = today'缩小到今天然后用他们的id查询表格匹配。 – flaschenpost 2013-05-12 12:52:47

相关问题