2012-08-26 41 views
2

我使用SQL优化来获得随机行

SELECT * 
    FROM picture 
INNER JOIN user ON picture.fbid = user.fbid 
WHERE hide = 0 
    AND userhide = 0 
ORDER BY gender, RAND() LIMIT 0 , 1 

此执行,给我的链接排随机,其中性别是女性的照片。大约需要15秒钟才能执行。

我怎么可能更改SQL,使其计算快?我应该在Picture表中添加一个性别列,以便它不会同时包含这个表,然后获取一个随机行或者还有其他方法来优化SQL?

+0

为什么这个标签'[MySQL的]'和'[SQL服务器]'?这是什么,你有什么指标,目前的解释计划是什么? – Ben

+0

其MYSQL ..... – Yahoo

+2

顺便说一句,有没有保证返回行会有性别为女......你需要用'和user.gender =“WHERE子句中female''。 – Ben

回答

3

[编辑]你可以做同样的一个MySQL的存储过程,我只是编码在这里:http://sqlfiddle.com/#!2/d0e6a/2

(注:由于没有在每一查询做会aliviate负载的数量,否则在此特殊情况下,它可以更慢,我会建议,让您的查询,但与指数优化或检查了这一点:Is cross-table indexing possible?

[编辑2]这是一个使用的50000随机的平均索引优化的另一个例子每个表中的条目:http://sqlfiddle.com/#!2/bfbe1/1查询需要少于100毫秒(没有索引我离开它运行几分钟,仍然没有结果!)。您可以使用CREATE INDEX

这是一个使用2个查询从PHP脚本我的解决方案建立在现有的表的索引:

$sql="SELECT COUNT(*) 
    FROM picture 
INNER JOIN user ON picture.fbid = user.fbid 
WHERE hide = 0 
    AND userhide = 0 
    AND gender = 'female' 
    GROUP BY gender"; 

$result=mysql_query($sql); 
$row=mysql_fetch_array($result); 

$sql="SELECT * 
     FROM picture 
     INNER JOIN user ON picture.fbid = user.fbid 
     WHERE hide = 0 
     AND userhide = 0 
     AND gender = 'female' 
     LIMIT FLOOR(RAND()*$row['COUNT(*)']),1"; 

$result=mysql_query($sql); 
$picture=mysql_fetch_array($result); 

这应该让你查询快了很多。

另外,如果你的表是很大的(我猜是这种情况,因为查询需要15秒),这将有助于如果有条件/连接字段建立索引。

+0

加入溶液作为存储过程,则可以避免发送多个查询,检查出来;) – NotGaeL

+0

SQL小提琴50000条记录?尔加!这不是用于原始性能测试(因为它受许多不同变量的影响);作为测试用例,SQL小提琴应该可以帮助您制作查询的结构。相对表现可以通过比较执行计划来判断。我想我需要在MySQL数据库大小设置硬限制,以防止这样的事情 - 它太硬的服务器上,如果每个人都这样说。 –

+0

你说得对,我会牢记这一点。无论如何,我还在我的笔记本电脑上使用virtualbox(1 GHz 1核心,1 GB RAM)进行了一些“实际”RAW测试,并获得了均匀分布的随机记录(每张桌上约有5000万)。然后我发现'count(*)'query +'limit floor(rand()* count),1'在这种情况下查询并不是最优化的:在这台虚拟机上处理需要200到400秒之间,一个稳定的200以及'rand by(order by rand)'解决方案,我猜这取决于有多少记录匹配查询(在这种情况下,平均值为3125000)。 – NotGaeL