【问题标题】:MySQL - searching a self join and ranges or dataMySQL - 搜索自联接和范围或数据
【发布时间】:2013-07-20 08:25:43
【问题描述】:

我的任务是在我当地的社区中心及时为情人节打造一款“新婚”类型的游戏,所以不要着急!

所以,我们有 50 多对非常了解彼此的情侣将提前被问到 100 个问题。每个问题都有用户的回答和允许误差范围的范围(此范围配额将受到限制)。然后他们可以选择他们认为合作伙伴的答案,误差范围相同。

EG(我会像我和我的 GF 一样玩一局):

问题:你喜欢水果吗? 我对水果很挑剔,所以我会在 100 分中打出低分……比如 20 '将允许将是 30。 我认为她喜欢水果,并且至少会放 90 分。但她喜欢很多食物,所以可能会排名较低,所以我会给她 20 分。

好的,对 100 个问题和 50 对重复该过程。

我只剩下一张这样的桌子:

u_a = 用户回答

u_l = 用户误差水平

p_a = 合作伙伴答案

p_l = 合作伙伴误差水平

CREATE TABLE IF NOT EXISTS `large` (
`id_user` int(11) NOT NULL,
`id_q` int(11) NOT NULL,
`u_a` int(11) NOT NULL,
`u_l` int(11) NOT NULL,
`p_a` int(11) NOT NULL,
`p_l` int(11) NOT NULL,
KEY `id_user` (`id_user`,`id_q`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='Stackoverflow Test';

所以我的行将在前面的示例中:

(1, 1, 20, 30, 90, 20)

我的任务是搜索所有用户,看看谁是 50 人中最匹配的人。(并希望情侣们在一起好!)。

我想在数据库中搜索我对合作伙伴的回答与他们的回答匹配的所有用户,但对于每个用户。

这是我到目前为止所得到的(注意我已经注释掉了一些代码,这是因为我正在尝试两种方法,但不确定哪种方法最好):

SELECT
match.id_user,
count(*) as count
from `large` `match`
INNER JOIN `large` `me` ON me.id_q = match.id_q
WHERE
me.id_user = 1 AND
match.id_user != 1 AND
GREATEST(abs(me.p_a - match.u_a), 0) <= me.p_l
AND
GREATEST(abs(match.p_a - me.u_a), 0) <= match.p_l 

#match.u_a BETWEEN GREATEST(me.p_a - me.p_l, 0) AND (me.p_a + me.p_l)
#AND
#me.u_a BETWEEN GREATEST(match.p_a - match.p_l, 0) AND (match.p_a + match.p_l)

GROUP BY match.id_user

ORDER BY count DESC

我今天的问题是:

此查询需要 AGES 时间!我想在游戏期间这样做,让用户有机会在晚上更改答案并获得即时结果,所以这必须很快。为我(用户 1)查找所有匹配项时,我正在查看 40 秒。

我现在正在阅读有关数据库引擎和索引的信息,以确保我尽我所能...但欢迎提出建议!

干杯和 PHEW!

【问题讨论】:

    标签: mysql search join indexing


    【解决方案1】:

    您的查询不应在较小的数据集上花费 40 秒。了解发生了什么的最好方法是在查询之前使用explain

    但是,我怀疑问题出在me 上。 MySQL 引擎可能会为所有用户创建所有可能的组合,然后 将您过滤掉。您可以通过修改此代码来测试:

    from `large` `match` INNER JOIN
         `large` `me`
         ON me.id_q = match.id_q
    WHERE me.id_user = 1 AND
          match.id_user != 1 AND . . . .
    

    收件人:

    from `large` `match` INNER JOIN
         (select me.*
          from `large` `me`
          where me.id_user = 1
         ) me
         ON me.id_q = match.id_q
    WHERE match.id_user != 1 AND . . . .
    

    此外,以下索引可能有助于查询:large(id_user, id_q)large(id_q)

    【讨论】:

    • 我正在尝试更多的用户和更多的问题,以使其真正做到无懈可击。我刚刚意识到我的测试表超过 1500 万行!!!我内心的极客想让它仍然工作......我应该可以克服那个......
    • @Beertastic 。 . .你在为整个国家做情人节吗?您的社区中心是否计划进行大规模收购,比如说接管世界? LOL 在那种情况下,40 秒还不错。而且,您学到了一些关于开发测试脚本的知识(提示:truncate table 非常有用)。
    • 你说得对......我刚刚截断了 50 个用户,每个用户有 100 个 q ......快如闪电!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-22
    • 2011-02-06
    • 1970-01-01
    • 2012-03-03
    • 1970-01-01
    • 2014-11-01
    相关资源
    最近更新 更多