<?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 Order By Rand()，及随机查数据。]]></title> 
<author>jack &lt;xdy108@126.com&gt;</author>
<category><![CDATA[WEB2.0]]></category>
<pubDate>Tue, 20 Jul 2010 05:58:41 +0000</pubDate> 
<guid>http://www.jackxiang.com/post//</guid> 
<description>
<![CDATA[ 
	<div class="code">select FQQ** from Tbl_User_*** Order By Rand() limit 50; </div><br/><br/>最近由于需要大概研究了一下MYSQL的随机抽取实现方法。举个例子，要从tablename表中随机提取一条记录，大家一般的写法就是：SELECT * FROM tablename ORDER BY RAND() LIMIT 1。<br/><br/>但是，后来我查了一下MYSQL的官方手册，里面针对RAND()的提示大概意思就是，在ORDER BY从句里面不能使用RAND()函数，因为这样会导致数据列被多次扫描。但是在MYSQL 3.23版本中，仍然可以通过ORDER BY RAND()来实现随机。<br/><br/>但是真正测试一下才发现这样效率非常低。一个15万余条的库，查询5条数据，居然要8秒以上。查看官方手册，也说rand()放在ORDER BY 子句中会被执行多次，自然效率及很低。<br/><br/>搜索Google，网上基本上都是查询max(id) * rand()来随机获取数据。<br/>SELECT * FROM `table` AS t1 JOIN (SELECT ROUND(RAND() * (SELECT MAX(id) FROM `table`)) AS id) AS t2 WHERE t1.id &gt;= t2.id ORDER BY t1.id ASC LIMIT 5;<br/><br/>但是这样会产生连续的5条记录。解决办法只能是每次查询一条，查询5次。即便如此也值得，因为15万条的表，查询只需要0.01秒不到。<br/><br/>下面的语句采用的是JOIN，mysql的论坛上有人使用<br/><br/>SELECT * FROM `table` WHERE id &gt;= (SELECT FLOOR( MAX(id) * RAND()) FROM `table` ) ORDER BY id LIMIT 1;<br/><br/>我测试了一下，需要0.5秒，速度也不错，但是跟上面的语句还是有很大差距。总觉有什么地方不正常。<br/><br/>于是我把语句改写了一下。<br/>SELECT * FROM `table` <br/>WHERE id &gt;= (SELECT floor(RAND() * (SELECT MAX(id) FROM `table`)))  <br/>ORDER BY id LIMIT 1;<br/><br/>这下，效率又提高了，查询时间只有0.01秒<br/><br/>最后，再把语句完善一下，加上MIN(id)的判断。我在最开始测试的时候，就是因为没有加上MIN(id)的判断，结果有一半的时间总是查询到表中的前面几行。<br/>完整查询语句是：<br/>SELECT * FROM `table` <br/>WHERE id &gt;= (SELECT floor( RAND() * ((SELECT MAX(id) FROM `table`)-(SELECT MIN(id) FROM `table`)) + (SELECT MIN(id) FROM `table`)))  <br/>ORDER BY id LIMIT 1;<br/><br/>SELECT * <br/>FROM `table` AS t1 JOIN (SELECT ROUND(RAND() * ((SELECT MAX(id) FROM `table`)-(SELECT MIN(id) FROM `table`))+(SELECT MIN(id) FROM `table`)) AS id) AS t2 <br/>WHERE t1.id &gt;= t2.id <br/>ORDER BY t1.id LIMIT 1;<br/><br/>最后在php中对这两个语句进行分别查询10次，<br/>前者花费时间 0.147433 秒<br/>后者花费时间 0.015130 秒<br/>看来采用JOIN的语法比直接在WHERE中使用函数效率还要高很多。<br/>来源：http://blog.csdn.net/zxl315/article/details/2435368<br/><br/>一）没有Id怎么办，也就是没有索引，当然是加索引Id，再就是，可以采取如下SQL，但效率肯定不是很好：<br/><textarea name="code" class="C" rows="15" cols="100">
SELECT * FROM Bar B JOIN (SELECT CEIL(MAX(ID)*RAND()) AS ID FROM Bar) AS m ON B.ID &gt;= m.ID LIMIT 1;
SELECT * FROM video_upload_table B JOIN (SELECT CEIL(MAX(uuid)*RAND()) AS uuid FROM video_upload_table) AS m ON B.uuid &gt;= m.uuid LIMIT 1;
SELECT * FROM video_upload_table B JOIN (SELECT CEIL(MAX(user_id)*RAND()) AS user_id FROM video_upload_table) AS m ON B.user_id &gt;= m.user_id LIMIT 1;
</textarea><br/><br/>二）加索引Id，摘录自：http://www.jackxiang.com/post/821/<br/><textarea name="code" class="php" rows="15" cols="100">
&nbsp;&nbsp;&nbsp;&nbsp;ALTER TABLE `video_table`&nbsp;&nbsp;ADD `id` INT(64) NOT NULL&nbsp;&nbsp;&nbsp;&nbsp;first;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;alter table `video_table` add index id(id);&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;ALTER TABLE `video_table`&nbsp;&nbsp;modify&nbsp;&nbsp;`id` INT(64) NOT NULL AUTO_INCREMENT&nbsp;&nbsp; first;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;-----------------------------------------------------------------------&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;mysql&gt; ALTER TABLE `video_table`&nbsp;&nbsp;ADD `id` INT(64) NOT NULL&nbsp;&nbsp;&nbsp;&nbsp;first;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;Query OK, 162090 rows affected (1 min 7.06 sec)&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;Records: 162090&nbsp;&nbsp;Duplicates: 0&nbsp;&nbsp;Warnings: 0&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;mysql&gt; alter table `video_table` add index id(id);&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;Query OK, 0 rows affected (10.94 sec)&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;Records: 0&nbsp;&nbsp;Duplicates: 0&nbsp;&nbsp;Warnings: 0&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;mysql&gt; ALTER TABLE `video_table`&nbsp;&nbsp;modify&nbsp;&nbsp;`id` INT(64) NOT NULL AUTO_INCREMENT&nbsp;&nbsp; first;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;Query OK, 162090 rows affected (1 min 10.35 sec)&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;Records: 162090&nbsp;&nbsp;Duplicates: 0&nbsp;&nbsp;Warnings: 0&nbsp;&nbsp;
</textarea><br/>Innodb在加自增长id有点特殊，更多请看：http://www.jackxiang.com/post/821/<br/>加上Id后效率情况，后查询SQL如下，这样整确实时间上少了不少：<br/><textarea name="code" class="php" rows="15" cols="100">
SELECT *
FROM `video_table` AS t1 JOIN (SELECT ROUND(RAND() * ((SELECT MAX(id) FROM `video_table`)-(SELECT MIN(id) FROM `video_table`))+(SELECT MIN(id) FROM `video_table`)) AS id) AS t2
WHERE t1.id &gt;= t2.id
ORDER BY t1.id LIMIT 1 &#92;G;

1 row in set (0.03 sec)

</textarea><br/><br/>  MySql查询随机几条数据<br/>    想到了  Max  RAND  这几个函数<br/>    用以下2种办法都可以实现查询。  速度还行。<br/>    几十万数据左右， 没有什么问题。<br/>    SELECT * FROM `news`<br/>    WHERE id &gt;= (SELECT floor(RAND() * (SELECT MAX(id) FROM `news`))) <br/>    LIMIT 10;<br/>    <br/>    <br/>    SELECT *<br/>    FROM `news` AS t1 JOIN (SELECT ROUND(RAND() * ((SELECT MAX(id) FROM `news`)-(SELECT MIN(id) FROM `news`))+(SELECT MIN(id) FROM `news`)) AS id) AS t2<br/>    WHERE t1.id &gt;= t2.id<br/>  LIMIT 10;<br/>    <br/>    <br/>    <br/>  
]]>
</description>
</item><item>
<link>http://www.jackxiang.com/post//#blogcomment</link>
<title><![CDATA[[评论] MySQL Order By Rand()，及随机查数据。]]></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>