2010-11-11 56 views
1

如何避免对此查询使用临时表并仍然实现相同的目标?如何避免对此简单查询使用临时表

EXPLAIN EXTENDED 
SELECT DISTINCT id, view_count 
    FROM 
     screenshot_udb_affect_assoc 
    INNER JOIN 
     screenshot ON id = screenshot_id 
    WHERE unit_id = 110 LIMIT 0, 6 

id select_type table type possible_keys key key_len ref rows filtered Extra 
1 SIMPLE screenshot_udb_affect_assoc ref screenshot_id,unit_id unit_id 4 const 34 100.00 Using temporary 
1 SIMPLE screenshot eq_ref PRIMARY PRIMARY 4 source_core.screenshot_udb_affect_assoc.screenshot... 1 100.00 

我已经不再更新了查询不使用RAND(),取而代之的是LIMIT将通过PHP是随机的。虽然它仍然显示,它的使用临时表

+0

'unit_id'属于'screensho't吗? 'unit_id = 110'有多少个截图?每个“截图”有多少个“screenshot_udb_affect_assoc”? – Quassnoi 2010-11-11 20:12:53

+0

给定单元的大约150个屏幕截图,每个屏幕截图可能需要12-15个单元 – Webnet 2010-11-11 21:42:47

+0

您能否提供一个新查询看起来像您正在制作的示例(最好使用EXPLAIN以及)? – 2010-11-12 07:50:41

回答

2
SELECT rnd_id, rnd_value 
FROM (
     SELECT @cnt := COUNT(*) + 1, 
       @lim := 6 
     FROM screenshot 
     JOIN screenshot_udb_affect_assoc 
     ON  screenshot_id = id 
     WHERE unit_id = 110 
     ) vars 
STRAIGHT_JOIN 
     (
     SELECT r.*, 
       @lim := @lim - 1 
     FROM (
       SELECT id, view_count 
       FROM screenshot 
       JOIN screenshot_udb_affect_assoc 
       ON  screenshot_id = id 
       WHERE unit_id = 110 
       ) r 
     WHERE (@cnt := @cnt - 1) 
       AND RAND() < @lim/@cnt 
     ) i 

在这篇文章中详细解释:

这仍然需要在满足查询的所有行两次扫描,但没有filesort

创建以下指标:

screenshot (unit_id) 
screenshot_udb_affect_assoc (screenshot_id) 
+0

我讨厌不使用它,但是如果它需要两次扫描,我真的想试着一次扫描一次,如果可以的话。 – Webnet 2010-11-12 00:24:19

+0

@Webnet:你可以用粗略估计替换COUNT(*)。随机性会受到一点影响,但只会在一次扫描中完成。 – Quassnoi 2010-11-12 00:29:52

2

ORDER BY RAND()自动导致创建临时表。

它的工作原理是创建一个包含随机数的新列的临时表。然后它使用ORDER BY对临时表执行查询。

为避免使用临时表,您必须找到一种选择随机数的新方法。

我之前使用的解决方案(依赖于行未被删除)是在表上执行SELECT COUNT,然后选择该范围内的随机数并仅选择那些行。

还有一些其他解决方案,但ORDER BY RAND()不是一个好的解决方案。

相关问题