<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title><![CDATA[向东博客 专注WEB应用 构架之美 --- 构架之美，在于尽态极妍 | 应用之美，在于药到病除]]></title> 
<link>http://www.jackxiang.com/index.php</link> 
<description><![CDATA[赢在IT，Playin' with IT,Focus on Killer Application,Marketing Meets Technology.]]></description> 
<language>zh-cn</language> 
<copyright><![CDATA[向东博客 专注WEB应用 构架之美 --- 构架之美，在于尽态极妍 | 应用之美，在于药到病除]]></copyright>
<item>
<link>http://www.jackxiang.com/post//</link>
<title><![CDATA[【邮件讨论组】高效的mysql分页]]></title> 
<author>jack &lt;xdy108@126.com&gt;</author>
<category><![CDATA[WEB2.0]]></category>
<pubDate>Thu, 30 Apr 2009 08:13:18 +0000</pubDate> 
<guid>http://www.jackxiang.com/post//</guid> 
<description>
<![CDATA[ 
	http://chaoqun.17348.com/2009/04/efficient-pagination-using-mysql/<br/><br/>相信这是个大家都常见的问题，解决方式各自不一，欢迎交流，尤其是对分页有需求的<br/>这种分页原理比普通的分页更聪明一些<br/><br/>谢谢分享.<br/>但有时候分页会带很多条件... 减少扫描范围是个不错手段.<br/>这东西理解起来并不难，看到这篇介绍前，同系统开发的一个数据库工程师聊过相应的<br/>方法：<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;一是精确定位，就是limit m，n&nbsp;&nbsp;将m做好定位，减少磁盘扫描<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;二是针对跨度一次多取，就目前的情况看，页面分页都是由限制的10页，或20<br/>页，将10也或20页作为一组，一次取出。也能减少不小的消耗。<br/><br/>我们的情况可能会更复杂一些，比如datacache（mc）、pagecache（squid）等，在存<br/>在cache的情况下，删cache也会带来一些小的问题。欢迎扩展话题。<br/><br/>见过gg的分页是带开始id和结束id的<br/><br/>直接给出page,无法知道上一次查询的id,可以改造一下必须查库的分页程序.<br/><br/>是不是说当m不写的时候会更快呢.也就是每次分页取上次分页的最后一个id,+1或-1.<br/><br/>直接limit n.<br/><br/>但话又说回来:<br/><br/>往往慢是因为count,count需要扫描全表.<br/>重新学习了一下，找到两篇文档，分享一下：<br/><br/>http://www.mysqlperformanceblog.com/2007/04/10/count-vs-countcol/<br/><br/>http://imysql.cn/2008_06_24_speedup_innodb_count<br/><br/>其实有一个常量可以获取总条数的 SQL_CALC_FOUND_ROWS,不受limit 影响.<br/>顺便请树新略微介绍一下SQL_CALC_FOUND_ROWS 吧。<br/><br/><br/>以下是select 语句的语法:<br/>SELECT<br/>&nbsp;&nbsp;&nbsp;&nbsp;[ALL &#124; DISTINCT &#124; DISTINCTROW ]<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[HIGH_PRIORITY]<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[STRAIGHT_JOIN]<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT]<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[SQL_CACHE &#124; SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS]<br/>&nbsp;&nbsp;&nbsp;&nbsp;select_expr, ...<br/>&nbsp;&nbsp;&nbsp;&nbsp;[FROM table_references<br/>&nbsp;&nbsp;&nbsp;&nbsp;[WHERE where_condition]<br/>&nbsp;&nbsp;&nbsp;&nbsp;[GROUP BY &#123;col_name &#124; expr &#124; position&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[ASC &#124; DESC], ... [WITH ROLLUP]]<br/>&nbsp;&nbsp;&nbsp;&nbsp;[HAVING where_condition]<br/>&nbsp;&nbsp;&nbsp;&nbsp;[ORDER BY &#123;col_name &#124; expr &#124; position&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[ASC &#124; DESC], ...]<br/>&nbsp;&nbsp;&nbsp;&nbsp;[LIMIT &#123;[offset,] row_count &#124; row_count OFFSET offset&#125;]<br/>&nbsp;&nbsp;&nbsp;&nbsp;[PROCEDURE procedure_name(argument_list)]<br/>&nbsp;&nbsp;&nbsp;&nbsp;[INTO OUTFILE 'file_name' export_options<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#124; INTO DUMPFILE 'file_name'<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#124; INTO @var_name [, @var_name]]<br/>&nbsp;&nbsp;&nbsp;&nbsp;[FOR UPDATE &#124; LOCK IN SHARE MODE]]<br/><br/>SQL_CALC_FOUND_ROWS 在查询的时候指定,查询完成后,再调用 select FOUND_ROWS()<br/>获取满足条件的不受limit 影响的总行数.<br/><br/>总行数是在查询的同时计算的,再通过select FOUND_ROWS() 获取即可.<br/><br/> <br/><br/>mysql 5手册上的说明: <br/><br/>SQL_CALC_FOUND_ROWS tells MySQL to calculate how many rows there would be in<br/>the result set, disregarding any LIMIT clause. The number of rows can then<br/>be retrieved with SELECT FOUND_ROWS(). <br/><br/> <br/><br/>用法:&nbsp;&nbsp;select SQL_CALC_FOUND_ROWS&nbsp;&nbsp;field1,field2,....&nbsp;&nbsp;from table where<br/>condition limit n,n+m;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;select FOUND_ROWS();<br/><br/>我认为这个 SQL_CALC_FOUND_ROWS 的功效与 count()没有太大的区别。<br/><br/>实验了一下：<br/><br/> <br/><br/>mysql> select SQL_CALC_FOUND_ROWS id from wall_1c limit 1;<br/>+----+<br/>&#124; id &#124;<br/>+----+<br/>&#124;&nbsp;&nbsp;1 &#124;<br/>+----+<br/>1 row in set (26.29 sec)<br/><br/>mysql> select found_rows();<br/>+--------------+<br/>&#124; found_rows() &#124;<br/>+--------------+<br/>&#124;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1847998 &#124;<br/>+--------------+<br/>1 row in set (0.11 sec)<br/><br/><br/>mysql> select id from wall_1c limit 1;<br/>+----+<br/>&#124; id &#124;<br/>+----+<br/>&#124;&nbsp;&nbsp;1 &#124;<br/>+----+<br/>1 row in set (0.00 sec)<br/><br/> <br/><br/>mysql> select count(id) from wall_1c ; //已经切换了机器，避免缓存的影响。<br/>+-----------+<br/>&#124; count(id) &#124;<br/>+-----------+<br/>&#124;&nbsp;&nbsp; 1848008 &#124;<br/>+-----------+<br/>1 row in set (17.93 sec)<br/><br/> <br/><br/> <br/><br/>以上是用的InnoDB Engine。<br/><br/> <br/><br/>理论上说，SQL_CALC_FOUND_ROWS 也不会有什么先进的办法快速获取总条目数。<br/><br/><br/><br/>那个mysqlperformanceblog有过一篇关于SQL_CALC_FOUND_ROWS的测试<br/><br/>http://www.mysqlperformanceblog.com/2007/08/28/to-sql_calc_found_rows-or-not<br/>-to-sql_calc_found_rows/<br/><br/>文章地结论：<br/><br/>obvious conclusion from this simple test is: when we have appropriate<br/>indexes for WHERE/ORDER clause in our query, it is much faster to use two<br/>separate queries instead of one with SQL_CALC_FOUND_ROWS.<br/><br/> <br/><br/>当查询语句中的WHERE和ORDER的条件有合适的索引，选择两次查询而不是<br/>SQL_CALC_FOUND_ROWS<br/><br/><br/>这个问题是否可以这样理解，<br/><br/>如果需要结果集，那么通过SQL_CALC_FOUND_ROWS，先取得结果集，然后通过<br/>SQL_FOUND_ROWS取得所得行数。如果不需要结果集，该用count就用count吧。<br/><br/>同时，需要关注count(col) 和 count(*) 的差别<br/><br/>我认为这个 SQL_CALC_FOUND_ROWS 的功效与 count()没有太大的区别。<br/><br/>实验了一下：<br/><br/> <br/><br/>mysql> select SQL_CALC_FOUND_ROWS id from wall_1c limit 1;<br/>+----+<br/>&#124; id &#124;<br/>+----+<br/>&#124;&nbsp;&nbsp;1 &#124;<br/>+----+<br/>1 row in set (26.29 sec)<br/><br/>mysql> select found_rows();<br/>+--------------+<br/>&#124; found_rows() &#124;<br/>+--------------+<br/>&#124;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1847998 &#124;<br/>+--------------+<br/>1 row in set (0.11 sec)<br/><br/><br/>mysql> select id from wall_1c limit 1;<br/>+----+<br/>&#124; id &#124;<br/>+----+<br/>&#124;&nbsp;&nbsp;1 &#124;<br/>+----+<br/>1 row in set (0.00 sec)<br/><br/> <br/><br/>mysql> select count(id) from wall_1c ; //已经切换了机器，避免缓存的影响。<br/>+-----------+<br/>&#124; count(id) &#124;<br/>+-----------+<br/>&#124;&nbsp;&nbsp; 1848008 &#124;<br/>+-----------+<br/>1 row in set (17.93 sec)<br/><br/> <br/><br/> <br/><br/>以上是用的InnoDB Engine。<br/><br/> <br/><br/>理论上说，SQL_CALC_FOUND_ROWS 也不会有什么先进的办法快速获取总条目数。<br/>那个mysqlperformanceblog有过一篇关于SQL_CALC_FOUND_ROWS的测试<br/><br/>http://www.mysqlperformanceblog.com/2007/08/28/to-sql_calc_found_rows-or-not<br/>-to-sql_calc_found_rows/<br/><br/> <br/><br/>文章地结论：<br/><br/>obvious conclusion from this simple test is: when we have appropriate<br/>indexes for WHERE/ORDER clause in our query, it is much faster to use two<br/>separate queries instead of one with SQL_CALC_FOUND_ROWS.<br/><br/> <br/><br/>当查询语句中的WHERE和ORDER的条件有合适的索引，选择两次查询而不是<br/>SQL_CALC_FOUND_ROWS<br/><br/><br/>
]]>
</description>
</item><item>
<link>http://www.jackxiang.com/post//#blogcomment</link>
<title><![CDATA[[评论] 【邮件讨论组】高效的mysql分页]]></title> 
<author> &lt;user@domain.com&gt;</author>
<category><![CDATA[评论]]></category>
<pubDate>Thu, 01 Jan 1970 00:00:00 +0000</pubDate> 
<guid>http://www.jackxiang.com/post//#blogcomment</guid> 
<description>
<![CDATA[ 
	
]]>
</description>
</item>
</channel>
</rss>