如何避免为此查询使用临时表并仍然实现相同的目标?
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 :(得分: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)
答案 1 :(得分:2)
ORDER BY RAND()
会自动导致创建临时表。
它的工作原理是创建一个临时表,其中包含一个用随机数填充的新列。然后,它使用ORDER BY
对临时表执行查询。
为避免使用临时表,您必须找到一种选择随机数的新方法。
我之前使用的解决方案(依赖于未删除的行)是在表上执行SELECT COUNT
,然后在该范围内选择随机数并仅选择这些行。
还有许多其他解决方案,但ORDER BY RAND()
不是一个好的解决方案。