Mysql面试题,优化:SELECT * FROM user LIMIT 10000,1.

SELECT * FROM user LIMIT 10000,1.
这条语句有很大问题,请优化它!并解释出现查询问题的原因?

阅读 4.4k
3 个回答

如果我去面试,我会这样答。
1.select *很有可能返回不需要的列,如果可以指定具体需要哪些列会更好,减少结果集整体大小。
2.limit 10000,1,分不同情况的优化。
对于user表主键id是连续的,可以改写select id,username,age from user where id > 10000 limit 1
对于user表主键id有断层的,对于select * from user limit 10000,1是没有优化空间的。要优化,必须加where条件,例如select id,username,age from user where user_city='广州' limit 10000,1,这样就可以改写成select id,username,age from user a inner join (select id from user where user_city='广州' limit 10000,1) b on a.id=b.id,但要配合覆盖索引idx(user_city)才有效果,优化的思想是先从比user表小的覆盖索引上获取到主键id,再回表到主键索引里获取其他列的数据。

3.在大多数情况下,主键id很有可能是断层的,而且假设实际需求就是select * from user limit 10000,1,加了where条件就不符合需求。那么这种情况下,就只能对表结构和表数据下手了,想办法将行数据大小减少,例如恰当地将varchar换成int,按照三范式减少数据冗余等,目的是使得每一个数据页能装下更多的行数据,即使全表扫描,读取尽可能少的数据页。

4.从SELECT * FROM user LIMIT 10000,1来看,就是简单的获取user表第10001条数据,看不到有什么实质的查询意义,而且对于select id,username from user limit 10000,1,这样在username列上有索引和无索引会使得返回结果集有可能是不一样的,应该结合业务逻辑来看看有没有优化空间。

这句话相当于 select * from user offset 10000 limit 1
myql中offset会占用大量的时间来查找,但是你这个语句中又不需要他,又会把他抛掉,造成没必要的问题。
应该先找到 10000条中最后那一条的主键,假设值就是 10000

select * from user where id > 10000 limit 1


通过主键的索引来快速定位,可以减少查询时间

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