MySQL分页的同时查询记录总数 SQL_CALC_FOUND_ROWS的性能测试

来源:互联网 发布:unity3d obj 文件导入 编辑:程序博客网 时间:2024/06/04 18:42

select * from auth_user

SELECT FOUND_ROWS() //返回查询记录的总数

select sql_calc_found_rows col_name from table_name limit 5,3;
select found_rows()


SELECT语句中加上修饰SQL_CALC_FOUND_ROWS

加上SQL_CALC_FOUND_ROWS之后,即使你用了limit n,m ,SELECT FOUND_ROWS() 仍会返回满足条件记录的总数。这样,你执行完 select 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/
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 手机开机按钮坏了怎么办 改了账号游戏角色消失怎么办 华为开机键坏了怎么办 抖音账号已重置怎么办 抖音账号被重置怎么办 吃鸡账号密码忘了怎么办 微信只记得账号忘了手机号怎么办 红米3开机键失灵怎么办 晚自习教室有许多虫子怎么办 泰迪吃草又呕吐怎么办 手机不断收到验证码信息怎么办 樱桃吃多了上火怎么办 过年不想回婆婆家过怎么办 旅行箱提手坏了怎么办 影棚人物后面有影子怎么办 微信运动图标不见了怎么办 逆光拍摄人黑了怎么办 单反镜头刮花了怎么办 股东各50股份不同意退股怎么办 退股没有协议他不愿意退钱怎么办 s7刷机有三星帐号id怎么办 做主播留不住人怎么办 直播间留不住人怎么办 淘宝直播间留不住人怎么办 干了一个月不发工资怎么办 16岁长白色头发怎么办 腾讯乘车码解约了怎么办 蓝洞棋牌客封号怎么办 草莓被蚂蚁吃了怎么办 脖子被种了草莓怎么办 2岁的宝宝说脏话怎么办 欠钱的人跑路了怎么办 美国非婚生子父亲不认怎么办 孕4个月肚子胀气怎么办 8个月孕妇感冒了怎么办 孕8个月感冒鼻塞怎么办 怀孕八个月感冒了怎么办 孕八个月咳嗽了怎么办 享物说同城自提怎么办 锤基意外怀孕怎么办 08 蛐蛐罐底翻砂了怎么办