我有两张表tbl_data
和tbl_user_data
tbl_data
的结构
id (int) (primary)
names (varchar)
dept_id (int)
tbl_user_data
的结构:
id (int) (primary)
user_id (int)
names_id (int)
tbl_data.id
和tbl_user_data.names_id
是外键
我的情况是我要从tbl_data
中选择25个随机条目,这些条目之前没有提供给特定用户。所以我创建了一个tbl_user_data
,它将存储user_id
和names_id
(来自已提供的tbl_data
)。
我有点困惑,如何代表这个查询,还是有其他方法可以有效地做到这一点?
注意: tbl_data
的参赛人数超过500万。
到目前为止,我已写过这篇文章,但似乎不对。
SELECT td.names, td.dept_id
FROM tbl_data AS td
LEFT JOIN tbl_user_data AS tud ON td.id = tud.names_id
WHERE tud.user_id !=2
ORDER BY RAND( ) LIMIT 25
答案 0 :(得分:1)
两件事:
首先......您需要LEFT JOIN .... IS NULL
模式来挑选尚未送达的商品。您需要在ON子句中提及用户ID才能使其正常工作。
SELECT td.names, td.dept_id
FROM tbl_data AS td
LEFT JOIN tbl_user_data AS tud ON td.id = tud.names_id
AND tud.user_id = 2
WHERE tud.id IS NULL
ORDER BY RAND( ) LIMIT 25
其次,ORDER BY RAND() LIMIT ...
在一张大桌子上表现糟糕。它必须选择整个表,然后对其进行排序,然后丢弃除了25个项目之外的所有项目。这是非常浪费的,永远不会表现得很好。
通过仅排序id
值,然后使用它们来获取其他信息,您可以减少浪费。
这会获得25个随机ID值。
SELECT td.id
FROM tbl_data AS td
LEFT JOIN tbl_user_data AS tud ON td.id = tud.names_id
AND tud.user_id = 2
WHERE tud.id IS NULL
ORDER BY RAND( )
LIMIT 25
这会获取您的姓名和dept_id值。
SELECT a.names, a.dept_id
FROM tbl_data AS a
JOIN (
SELECT td.id
FROM tbl_data AS td
LEFT JOIN tbl_user_data AS tud ON td.id = tud.names_id
AND tud.user_id = 2
WHERE tud.id IS NULL
ORDER BY RAND( )
LIMIT 25
) b ON a.id = b.id
但是,它仍然是浪费。您可能希望构建此tbl_data表的随机版本,然后按顺序使用它。你可以每天重新随机一次,就像这样。
DROP TABLE tbl_data_random;
INSERT INTO tbl_data_random FROM
SELECT *
FROM tbl_data
ORDER BY RAND()
这样你就不会一遍又一遍地进行排序,只是为了丢弃结果。相反,你偶尔随机化一次。
答案 1 :(得分:0)
在names_id和user_id上创建索引。为什么是user_id varchar? 如果需要varchar并且varchar非常长,请在user_id上创建部分索引。 您可以使用EXPLAIN来查看使用查询的索引。
答案 2 :(得分:0)
由于您没有从tbl_user_data中选择任何内容,因此您可以使用exists代替:
SELECT td.names, td.dept_id
FROM tbl_data AS td
where exists (
select 1
from tbl_user_data AS tud
where td.id = tud.names_id
and tud.user_id !=2
)
ORDER BY RAND( ) LIMIT 25
tbl_data(id)和tbl_user_data(names_id,user_id)的索引会有所帮助。