0

我有一张大表(大约 10m 行,目前所有的测试数据都是假的。)。

id user 和 action 都不是唯一的,但是一个用户只能执行一次操作。(这意味着 id_user 和 id_action 永远只有一个组合。

x 和 y 都只会是 1 - 100 的 INT

我已经索引了每一列。

CREATE TABLE IF NOT EXISTS `test` (
`id_user` int(11) NOT NULL,
`id_action` int(11) NOT NULL,
`x` int(11) NOT NULL,
`y` int(11) NOT NULL,
KEY `x` (`x`),
KEY `y` (`y`),
KEY `id_user` (`id_user`),
KEY `id_action` (`id_action`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

这是我正在尝试构建的游戏。

我想要做的是在表中搜索任何其他在 y 指定的范围内具有相似分数 x 的用户。

例如,如果用户 1 执行操作 1,在 x 中的得分为 75,在 y 中的范围为 10。我想显示得分在 65-85 之间的所有其他用户(因为范围是 10 在 y 中设置)。

这就是我所拥有的,我只是在本地笔记本电脑上运行它..它在 300 秒后超时...... :(

SELECT * FROM test
WHERE
id_user != 1 AND
x BETWEEN
((SELECT x from test WHERE id_action = 1 AND id_user = 1) - (100 - (SELECT y FROM test WHERE id_action = 1 And id_user = 1)))
AND
((SELECT x from test WHERE id_action = 1 AND id_user = 1) + (100 - (SELECT y FROM test WHERE id_action = 1 And id_user = 1)));

对我拥有的 10,000,000 行的搜索(100 个操作和 100,000 个测试用户......所有随机数)只是失败了。

我现在要研究将表连接到自身,但我认为子选择会更有效。我去这里时正在学习......任何建议将不胜感激...... :)

4

1 回答 1

1

将其拆分为 2 个查询要容易得多,一个用于获取 x 的范围,另一个用于进行实际检索。

如果您真的只想在一个查询中执行此操作,可以试试这个

Select t0.* from test t0, test t1 where t1.id_user=1 AND t0.id_user !=1 
AND abs(t1.x-t0.x) <= t1.y 

此查询是自联接,我很确定它的性能比您的查询好得多。我还使用 abs 函数来过滤 x 范围。顺便说一句,我假设 y 是范围(例如 10),目标 x 范围是从 t1.x - t0.y 到 t1.x + t0.y。我对您查询中的“100 - (select y ....”) 感到困惑。

于 2013-07-20T13:11:06.073 回答