请问这个SQL为什么不会用到索引,该怎么优化?

现在有两张表;r和p,在r_id上有索引

SELECT * FROM  p,  r WHERE r.r_id= p.c_id OR r.r_id=p.p_id;

现在这个sql通过explain查看发现r表是ALL全表扫描,请问为什么不使用索引,该如何优化,谢谢诸位

阅读 4.8k
7 个回答

拆成SELECT FROM p, r WHERE r.r_id= p.c_id union SELECT FROM p, r WHERE r.r_id=p.p_id;

都没人看到他没有条件筛选吗? 两个表一起查,不论你怎么关联肯定要遍历数据的,这样必然会有一个表要全扫的

我创建了p表和r表,并按照你描述的,在r表上添加了r_id字段的索引,做了测试后来回答你的问题:

索引失效问题

虽然添加了索引,但是

explain SELECT FROM p, r WHERE r.r_id= p.c_id union SELECT FROM p, r WHERE r.r_id=p.p_id;

这种联查导致索引失效。

可以试着下面这种写法:

explain select * from p where c_id in (select r_id from r)
union all 
select * from p where p_id in (select r_id from r)

通过图中的结果可以看到,索引已经起作用了:
idx_r_id

继续优化

  • 尽量少用select *
  • 在p表中加入索引
  • 调整sql语句的写法,避免出现全表索引

参考:http://www.cnblogs.com/han-10...

where 语句里面如果带有or条件, myisam表能用到索引, innodb不行,or必须是独立的索引

SELECT * FROM  r , p WHERE r.r_id = p.c_id
UNION
SELECT * FROM  r , p WHERE r.r_id = p.p_id

对于单个查询,IN是可以命中r.r_id索引,这是由mysql查询引擎自己决定。

1.多表联合查询,需要加筛选条件才能走索引,否则第二张表会扫全表。
2.一般union all多用来替代or,比union效率高,union适用于需要去重的场合,但是如果存在全表扫,union可能效率更低。
3.有时候可能因为数据量的大小,块分布,逻辑读次数等,实际结果可能反差很大,到底用哪种更快,不是绝对的,多用explain来看一下,数据量过大的情况,可以考虑分库分表,或者缓存的方式来处理,或者将部分逻辑计算放到代码层面处理。

有没有试试join呢?

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题