分页程序一般由两条SQL组成:

SELECT COUNT(*) FROM ... WHERE ....
SELECT ... FROM ... WHERE LIMIT ...

  如果使用SQL_CALC_FOUND_ROWS的话,一条SQL就可以了:

SELECT SQL_CALC_FOUND_ROWS ... FROM ... WHERE LIMIT ...

  在得到数据后,通过FOUND_ROWS()可以得到不带LIMIT的结果数:

SELECT FOUND_ROWS()

  看上去,似乎SQL_CALC_FOUND_ROWS应该快于COUNT(*),但实际情况并不是这样简单,请看:

  To SQL_CALC_FOUND_ROWS or not to SQL_CALC_FOUND_ROWS?

  用数据说话,证明了COUNT(*)相对SQL_CALC_FOUND_ROWS来说更快。不过我觉得这个结论也不全面,某些情况下,SQL_CALC_FOUND_ROWS更有优势,看我的实验:

  表结构如下:


CREATE TABLE IF NOT EXISTS `foo` (
`a` int(10) unsigned NOT NULL AUTO_INCREMENT,
`b` int(10) unsigned NOT NULL,
`c` varchar(100) NOT NULL,
PRIMARY KEY (`a`),
KEY `bar` (`b`,`a`)
) ENGINE=MyISAM;

  导入一些测试数据:

for ($i = 0; $i <10000; $i++) {
mysql_query("INSERT INTO foo SET b=ROUND(RAND()*10), c=MD5({$i})");
}

  先测试COUNT(*)方式:


$start = microtime(true);
for ($i = 0; $i < 1000; $i++) {
mysql_query("SELECT SQL_NO_CACHE COUNT(*) FROM foo WHERE b = 1");
mysql_query("SELECT SQL_NO_CACHE a FROM foo WHERE b = 1 LIMIT 100, 10");
}
$end = microtime(true);
echo $end - $start;

  结果输出(数据大小视测试机性能而定):0.75777006149292

  再测试SQL_CALC_FOUND_ROWS方式:


$start = microtime(true);
for ($i = 0; $i < 1000; $i++) {
mysql_query("SELECT SQL_NO_CACHE SQL_CALC_FOUND_ROWS a FROM foo WHERE b = 1 LIMIT 100, 10");
mysql_query("SELECT FOUND_ROWS()");
}
$end = microtime(true);
echo $end - $start;

  结果输出(数据大小视测试机性能而定):0.6681969165802

  有数据有真相,那为什么我的实验结论和MySQL Performance Blog的结论相悖呢?这是因为在MySQL Performance Blog的实验里,COUNT(*)查询是执行的的Covering Index,而SQL_CALC_FOUND_ROWS是执行的表查询;而在我的实验里,因为我定义了适当的索引,COUNT(*)和SQL_CALC_FOUND_ROWS都是执行的Covering Index,所以结论出现了差异。

  既然使用了Covering Index,就意味着不能再使用SELECT *的形式了,只能使用类似SELECT id这样的形式了,用的列在索引里都能查到,如此说来,我们需要的实际数据从哪来呢?这个很简单,有了主键之后,实际数据可以通过Key/Value形式的缓存获得,这样的架构很常见。

  结论:SQL_CALC_FOUND_ROWS如果执行的是Covering Index的话,是很快的!换个角度看,如果COUNT(*)和SQL_CALC_FOUND_ROWS都只能通过表查询来检索,那么分页时,SQL_CALC_FOUND_ROWS同样会快于COUNT(*),读者可自行测试。

http://kb.cnblogs.com/page/82986/

SQL_CALC_FOUND_ROWS。
SELECT SQL_CALC_FOUND_ROWS ... FROM ... WHERE LIMIT ...
所谓SQL_CALC_FOUND_ROWS是指在执行带LIMIT的查询时,附带统计一下如果不加LIMIT的话将会输出多少条结果。

在得到数据后,通过FOUND_ROWS()可以得到不带LIMIT的结果数:
SELECT FOUND_ROWS()

MySQL的SQL_CALC_FOUND_ROWS真的很慢么?的更多相关文章

  1. MySQL开发篇,存储引擎的选择真的很重要吗?

    前言 谁说MySQL查询千万级别的数据很拉跨?我今天就要好好的和你拉拉家常,畅谈到深夜,一起过除夕!这篇文章也是年前的最后一篇,希望能带给大家些许收获,不知不觉查找文档和参考实体书籍就写了这么多,自己 ...

  2. 值得推荐的C/C++框架和库 (真的很强大) c

    http://m.blog.csdn.net/mfcing/article/details/49001887 值得推荐的C/C++框架和库 (真的很强大) 发表于2015/10/9 21:13:14 ...

  3. 转-MySQL教程-写的很详细,赞一个

    原帖地址:https://www.w3cschool.cn/mysql/,谢谢原帖大人 MySQL是什么? MySQL安装 MySQL示例数据库 MySQL导入示例数据库 MySQL基础教程 MySQ ...

  4. mysql的SQL_CALC_FOUND_ROWS 使用 类似count(*) 使用性能更高

    mysql的SQL_CALC_FOUND_ROWS 使用 类似count(*) 使用性能更高 在很多分页的程序中都这样写: SELECT COUNT(*) from `table` WHERE ... ...

  5. 【转】 值得推荐的C/C++框架和库 (真的很强大)

    [转] 值得推荐的C/C++框架和库 (真的很强大) 值得学习的C语言开源项目 - 1. Webbench Webbench是一个在linux下使用的非常简单的网站压测工具.它使用fork()模拟多个 ...

  6. MYSQL的SQL_CALC_FOUND_ROWS 和count(*)

    mysql的SQL_CALC_FOUND_ROWS 和 count(*) 在很多分页的程序中都这样写: SELECT COUNT(*) from `table` WHERE ......;  查出符合 ...

  7. HTTP真的很简单

    原文:HTTP Made Really Easy因为我本身网络基础就很差,所以看到这篇文章一方面是学习网络知识,另一方面为了锻炼我蹩脚的英语水平,文中如有错误,欢迎浏览指正! 前言 在看这篇文章的时候 ...

  8. paip.解决 数据库mysql增加列 字段很慢添加字段很慢

    paip.解决 数据库mysql增加列 字段很慢添加字段很慢 #环境如下: mysql5.6    数据仅仅3w alter table xxx add column yyy int default ...

  9. 转:Eric Lippert:阅读代码真的很难

    转自:http://blog.jobbole.com/438/ 相关文章 微软资深软件工程师:阅读代码真的很难(第2篇) 阅读优秀代码是提高开发人员修为的一种捷径 学会阅读源代码 如何阅读大型代码库? ...

随机推荐

  1. poj2409 & 2154 polya计数+欧拉函数优化

    这两个题都是项链珠子的染色问题 也是polya定理的最基本和最经典的应用之一 题目大意: 用m种颜色染n个珠子构成的项链,问最终形成的等价类有多少种 项链是一个环.通过旋转或者镜像对称都可以得到置换 ...

  2. ASCII码表(0 - 255)

    目前计算机中用得最广泛的字符集及其编码,是由美国国家标准局(ANSI)制定的ASCII码(American Standard Code for Information Interchange,美国标准 ...

  3. velocity自定义动画

         话说好久没有写博客了,零星的整理了一些东西,没有形成系统,所以也没有在这里记录.        废话不多说了,进入今天的正题.不知道大家是否记得之前写过的一篇文章<制作炫酷的专题页面& ...

  4. java--文件过滤器和简单系统交互

    一.文件过滤器 /** * @Title: getFileByFilter * @Description: 根据正则rege获取给定路径及其子路径下的文件名(注意递归的深度不要太大) * @param ...

  5. java和javax都是Java的API包,java是核心包,javax的x是extension的意思,也就是扩展包。

    java和javax都是Java的API包,java是核心包,javax的x是extension的意思,也就是扩展包.

  6. struts2.1.*中再实现了一个servlet的方法

    学习Struts2也有一段时间了,今天用Servlet写了一个验证码,然后搬到Struts2中,惊奇地发现Servlet无法访问,出现404错误!后来折腾了半天,终于找出原因了.这也算我学习中的一个重 ...

  7. js验证表单并提交

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  8. EF中的自动追踪与代理

    自动追踪 EF框架会自动追踪实体的变化(通过比较实体的当前值与原始值). 默认情况下,以下方法会自动触发实体变化的追踪 DbSet.Find DbSet.Local DbSet.Remove DbSe ...

  9. HTML5 Canvas前台压缩图片并上传到服务器

    1.前台代码: <input id="fileOne" type="file" /> <input id="btnOne" ...

  10. 64位Windows 7平台安装32位Timesten,配置ODBC数据源

    问题: 由于系统版本原因,客户机只能安装32位的Timesten,但客户机的平台是64位的win 7,安装完成后按照常规的控制面板->管理工具->数据源(ODBC)打开的ODBC数据源管理 ...