1

我有 2 张桌子。

第一个- 表 t_games(别名 g)

column    type    
g_id      mediumint(8)    
t_id_1    smallint(5)    
t_id_2    smallint(5)    
g_team_1  varchar(50) 
g_team_2  varchar(50)
g_date    datetime    
g_live    tinyint(3)

主索引在 g_id 字段上设置,并且在 (t_id_1, t_id_2, g_date, g_live) 字段上设置了额外的复合索引。

第二- 表 t_teams(别名:t1 和 t2)

column    type    
t_id      smallint(5)    
t_gw_name varchar(50)
gw_cid    tinyint(3) 

主索引在 t_id 上设置。

更新表之间的关系

每场比赛有两支球队。在表 t_teams 中有团队的名称。在 t_games 表中,我保留与 t_teams 相关的 ID,以检索参与游戏的每个团队的名称。因此,要检索带有团队名称的游戏 ID:

SELECT g.g_id, t1.t_gw_name, t2.t_gw_name FROM t_games g
JOIN t_teams t1 ON (g.t_id_1 = t1.t_id)
JOIN t_teams t2 ON (g.t_id_2 = t2.t_id)

我的 SQL 查询:

SELECT g_id, t_id_1, t_id_2, g_team_1, g_team_2, g_date, g_live, t1.t_gw_name AS t_gw_name_1, t1.gw_cid AS gw_cid_1, t2.t_gw_name AS t_gw_name_2, t2.gw_cid AS gw_cid_2
FROM t_games g
JOIN t_teams t1 ON (t_id_1 = t1.t_id) JOIN t_teams t2 ON (t_id_2 = t2.t_id)
WHERE g.g_date < "2013-07-24 20:00:00" AND g.g_live < 2`

解释后我得到:`

1     SIMPLE            g       ALL         t_id_1        NULL    NULL    NULL       16     Using where
1     SIMPLE            t1     eq_ref       PRIMARY     PRIMARY     2     t_id_1     1     
1     SIMPLE            t2     eq_ref       PRIMARY     PRIMARY     2     t_id_2     1`

我尝试了许多索引表的组合,但我无法摆脱 ALL 扫描。

4

1 回答 1

1

在您的情况下(对于您显示的查询),您只需要一个涵盖单个column的索引g_date

而您看到的ALL原因是:

  1. 表中只有 16 行 (?)
  2. 您正在选择超过 ~30% 的表格行

在这两种情况下,扫描所有表比使用索引更容易。

所以要检查g_date索引是否有效:

  1. t_games用大约 1000 行填充表格
  2. 执行从t_games表中返回大约 10 行的查询

PS:

  1. 复合索引(g_date, g_live)不起作用,因为您对两列都有范围比较
  2. singleg_live不会很有效,因为它对该列的基数很低
于 2013-07-28T09:54:24.750 回答