优化limit、count查询

在写分页的时候,我们通常都会用limit来限制返回结果集的行数,比如:
select title, summary, created from news order by created desc limit 20, 10;
我们通过limit查询,取出新闻表中的第20~29之间的记录,假如我们的新闻数据非常多,我们要取出10000~10009之间的数据,那么我们写成:
select id, title, summary, created from news order by created desc limit 10000, 10;
Mysql执行这条SQL语句,会产生10010行数据,然后丢弃前10000行数据,将最后的10行数据返回给你,执行这条SQL语句的代价非常的高,所以,如果你表中的数据非常多,而你又需要分页,你的SQL语句最好写成下面这样:
SELECT id, title, summary, created FROM news 
INNER JOIN ( SELECT id FROM news ORDER BY created DESC LIMIT 10000, 10 ) AS a USING(id);
首先,你要为created建索引,所有order by的字段都应当建立索引,基于索引的排序总是会很快。
执行改写后的SQL语句,我们从索引上检索数据,取出所需要的行,并且只取出id列的数据,因为id也是索引,然后我们再连接表,取出所需要的其它列的数据。

通过优化后的limit语句,在大数据表的分页中我们可以取得更好的性能。

貌似关于大数据分页也是一个不错的考验水平的题目。


----------------------------------------------------------------------------粉葛----------------------------------------------------------------------------

在开发过程我们经常需要统计数据库表中的记录数,比如分页(分页不一定非要统计总记录数),我们常常会用下面的两种行式来获取总记录数:

select count(*) from news;
select count(id) from news;
这两种count写法,到底哪一种更快呢?很长一段时间我都认为count(id)会比count(*)要快,但事实上count(*)要比count(id)要快。
如果count()括号中写列名,count就会统计该列有值的次数。如下表所示:
news表
---------------------------------------------
  id |  name  |  summary |     content    |
---------------------------------------------
  1  |  aaa   |  aaa     |     aaaaa      |
---------------------------------------------
  2  |  bbb   |          |     bbbbb      |
---------------------------------------------
  3  |  ccc   |  ccc     |     ccccc      |
---------------------------------------------
执行:
select count(summary) from news;
获取的总记录数的值是2,而不是3。

如果count()括号中写*,通配符并不是匹配所有的列,而是直接统计行数,当执行没有where子句的count(*)时,MySQL的查询速度非常的快,因为MySQL事先已经知道表中的记录数量,但是如果执行含有where子句的count(*)时,MySQL同样会执行全表扫描,所以,我们应该尽量为where子句的列建立索引。

使用count的查询很难优化,因为很多情况都需要执行全表扫描,唯一的优化方式就是尽量为where子句的表建立索引,更多的时候我们应该调整应用程序,避免使用count,比如,大数据分页采用估算分页法等等。



你可能感兴趣的:(数据库)