在mysql中连接表没有正确使用索引?

时间:2012-08-15 03:19:23

标签: mysql sql join indexing explain

我正在尝试连接四个表并将结果输出到新表。我的代码如下所示:

create table tbl  
select a.dte, a.permno, (ret - rf) f0_xs_ret, (xs_ret - (betav*xs_mkt)) f0_resid, mkt_cap     last_year_mkt_cap, betav beta_value
from a inner join b using (dte)
inner join c on (year(a.dte) = c.yr and a.permno = c.permno)
inner join  d on (a.permno = d.permno and year(a.dte)-1 = year(d.dte));

所有表都有多个索引,对于表a(dte, permno)为表b标识唯一记录,dte id是表{的唯一记录{1}},c ID为唯一记录,对于表(yr, permno)d为唯一记录。查询的(dte, permno)部分的解释是:

select

为什么mysql必须读取这么多行来处理这个东西?如果我正确读到这个,它必须阅读+----+-------------+-------+--------+-------------------+---------+---------+---------- ------------------------+--------+-------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+--------+-------------------+---------+---------+---------- ------------------------+--------+-------------------+ | 1 | SIMPLE | d | ALL | idx1 | NULL | NULL | NULL | 264129 | | | 1 | SIMPLE | c | ref | idx2 | idx2 | 4 | achernya.d.permno | 16 | | | 1 | SIMPLE | b | ALL | PRIMARY,idx2 | NULL | NULL | NULL | 12336 | Using join buffer | | 1 | SIMPLE | a | eq_ref | PRIMARY,idx1,idx2 | PRIMARY | 7 | achernya.b.dte,achernya.d.permno | 1 | Using where | +----+-------------+-------+--------+-------------------+---------+---------+----------------------------------+--------+-------------------+ 行,这应该是一个好月份。

有人可以解释一下这里发生了什么吗?

1 个答案:

答案 0 :(得分:2)

MySQL必须读取行,因为您使用函数作为连接条件。 dte上的索引无法解决查询中的YEAR(dte)问题。如果你想快速实现这一点,那么将年份放在它自己的列中以在连接中使用并将索引移动到该列,即使这意味着一些非规范化。

对于索引中未应用函数的其他列,如果索引不会提供太多好处,或者它们不是索引中最左侧的列,则可能不会使用它们t在连接条件中使用该索引的最左前缀。

  

有时MySQL不使用索引,即使有索引也是如此。发生这种情况的一种情况是,优化器估计使用索引将需要MySQL访问表中非常大比例的行。 (在这种情况下,表扫描可能会快得多,因为它需要较少的搜索。)

http://dev.mysql.com/doc/refman/5.0/en/mysql-indexes.html