MySQL的SQL_CALC_FOUND_ROWS
分页程序一般由两条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/
MySQL之Covering Index
在网上随便搜搜,就能找到大把的关于MySQL优化的文章,不过里面很多都不准确,说个常见的:
SELECT a FROM ... WHERE b = ...
一般来说,很多文章会告诫你类似这样的查询,不要在“a”字段上建立索引,而应该在“b”上建立索引。这样做确实不错,但是很多时候这并不是最佳结果。为什么这样说?让我们先来分析一下查询的处理过程:在执行查询时,系统会查询“b”索引进行定位,然后再利用此定位去表里查询需要的数据“a”。也就是说,在这个过程中存在两次查询,一次是查询索引,另一次是查询表。那有没有办法用一次查询搞定问题呢?有,就是Covering Index!所谓Covering Index,就是说不必查询表文件,单靠查询索引文件即可完成。具体到此例中就是建立一个复合索引“b, a”,当查询进行时,通过复合索引的“b”部分去定位,至于需要的数据“a”,立刻就可以在索引里得到,从而省略了表查询的过程。
如果你想利用Covering Index,那么就要注意SELECT方式,只SElECT必要的字段,千万别SELECT *,因为我们不太可能把所有的字段一起做索引,虽然可以那样做,但那样会让索引文件过大,结果反倒会弄巧成拙。
如何才能确认查询使用了Covering Index呢?很简单,使用explain即可!只要在Extra里出现Using index就说明使用的是Covering Index。
知道了以上这些知识,估计对Coverging Index的了解也差不多了。再举两个例子,让大家印象深点:
(一)比如说在文章系统里统计总数的时候,一般的查询是这样的:
SELECT COUNT(*) FROM articles WHERE category_id = ...
当我们在category_id建立索引后,这个查询使用的就是Covering Index。
(二)比如说在文章系统里分页显示的时候,一般的查询是这样的:
SELECT id, title, content FROM article ORDER BY created DESC LIMIT 10000, 10;
通常这样的查询会把索引建在created字段(其中id是主键),不过当LIMIT偏移很大时,查询效率仍然很低,改变一下查询:
SELECT id, title, content FROM article
INNER JOIN (
SELECT id FROM article ORDER BY created DESC LIMIT 10000, 10
) AS page USING(id)
此时,建立复合索引"created, id"就可以在子查询里利用上Covering Index,快速定位id,查询效率嗷嗷的。
Covering Index并不是什么很难的概念,但是人们往往会忽视它的价值,希望本文能给你提个醒。
更多:http://blog.itpub.net/758322/viewspace-680921/
MySQL的SQL_CALC_FOUND_ROWS的更多相关文章
- mysql的SQL_CALC_FOUND_ROWS 使用
mysql的SQL_CALC_FOUND_ROWS 使用 标签: sqlmysqltable 2007-02-27 11:40 5073人阅读 评论(0) 收藏 举报 分类: Mysql数据库技术( ...
- MySQL中SQL_CALC_FOUND_ROWS的用法
1. SQL_CALC_FOUND_ROWS简述 在很多分页的程序中都这样写: #查出符合条件的记录总数 SELECT COUNT(*) from [table] WHERE ......; #查询当 ...
- mysql的SQL_CALC_FOUND_ROWS 使用 类似count(*) 使用性能更高
mysql的SQL_CALC_FOUND_ROWS 使用 类似count(*) 使用性能更高 在很多分页的程序中都这样写: SELECT COUNT(*) from `table` WHERE ... ...
- 黄聪:mysql的SQL_CALC_FOUND_ROWS 使用 类似count(*) 使用性能更高
mysql的SQL_CALC_FOUND_ROWS 使用 类似count(*) 使用性能更高 在很多分页的程序中都这样写: SELECT COUNT(*) from `table` WHERE ... ...
- MYSQL的SQL_CALC_FOUND_ROWS 和count(*)
mysql的SQL_CALC_FOUND_ROWS 和 count(*) 在很多分页的程序中都这样写: SELECT COUNT(*) from `table` WHERE ......; 查出符合 ...
- MySQL的SQL_CALC_FOUND_ROWS真的很慢么?
分页程序一般由两条SQL组成: SELECT COUNT(*) FROM ... WHERE .... SELECT ... FROM ... WHERE LIMIT ... 如果使用SQL_CALC ...
- mysql 中 SQL_CALC_FOUND_ROWS 功能
mysql 数据库不符合sql标准的地方不少,比如TIMESTAMP列的处理,字符串比较默认大小写不敏感什么的.有时候这些问题会让你很郁闷,尤其是对从其它数据库转过来的人来说.但有些功能倒也蛮有趣. ...
- mysql的SQL_CALC_FOUND_ROWS /FOUND_ROWS()
在很多分页的程序中都这样写: SELECT COUNT(*) from `table` WHERE ......; 查出符合条件的记录总数 SELECT * FROM `table` WHERE . ...
- mysql SQL_CALC_FOUND_ROWS
mysql> ,; +----+ | id | +----+ | | | | | | | | | | +----+ rows | +--------------+ ro ...
随机推荐
- Jsp与servlet之间页面跳转及参数传递实例(转)
原网址:http://blog.csdn.net/ssy_shandong/article/details/9328985 11. jsp与servlet之间页面跳转及参数传递实例 分类: Java ...
- notepad++中的python缩进问题
现在并没有遇到什么卵问题,但查到资料说会有问题,先记一笔,tab自动换4个空格 cmd /k "$(FULL_CURRENT_PATH)" & PAUSE & EX ...
- DIV+CSS相对IE8的兼容问题
CSS技巧: 1.div的垂直居中问题 vertical-align:middle; 将行距增加到和整个DIV一样高 line-height:200px; 然后插入文字,就垂直居中了.缺点是要控制内容 ...
- iOS开发,多个button数组,每个数组只能选中5项,多个数组只能选择3个。
由于常用xib,所以不想用代码写那么多个button.而且也懒的算位置 直接xib拉线成四个数组.水果,零食,饮料,甜点. 入题实现的功能就是,在这四个数组之中只能在3个数组只选中5项.有点绕(就比如 ...
- 【转】图解SQL的各种连接join
原帖地址:http://www.nowamagic.net/librarys/veda/detail/936 图解SQL的各种连接join 让你对SQL的连接一目了然 在 2011年12月22日 那天 ...
- gradle使用国内源
// 设置 maven 库地址 repositories { maven { url 'http://maven.oschina.net/content/groups/public/' } } ...
- 10_Jaxws使用自定义pojo发布服务
[简述] 查询三天的天气信息(天气概况.日期.温度),测试jaxws是否支持自定义pojo发布服务. [开发过程] 服务端: 1.自定义pojo(天气概况.日期.温度) 2.开发SEI接口及实现类 3 ...
- HDOJ 1176 免费馅饼 -- 动态规划
题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=1176 Problem Description 都说天上不会掉馅饼,但有一天gameboy正走在回家的小 ...
- 《C和指针》读书笔记——第三章 数据
1.typedef:为各种数据类型定义新名字 typedef char *ptr_to_char; ptr_to_char a;//声明a是一个指向字符的指针. 2.链接属性:extern;stat ...
- 3.bit-map
适用范围:可进行数据的快速查找,判重,删除,一般来说数据范围是int的10倍以下 基本原理及要点:使用bit数组来表示某些元素是否存在,比如8位电话号码 扩展:bloom filter可以看做是对bi ...