Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/61.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
MySQL超长查询,内部连接_Mysql_Sql_Join_Inner Join - Fatal编程技术网

MySQL超长查询,内部连接

MySQL超长查询,内部连接,mysql,sql,join,inner-join,Mysql,Sql,Join,Inner Join,我开发了一个两个团队可以面对面的网站。第一组为特定的值(堆栈)创建匹配搜索m,状态为=search。第一个团队具有elo(级别)属性。 当第二个团队(elo为150)搜索比赛时,我们执行以下查询: SELECT m.id, m.value, m.teamOneScore, m.teamTwoScore, m.date, m.status, m.detail, m.team_one_id, m.team_two_id FROM user_match m INNER JOIN team t ON

我开发了一个两个团队可以面对面的网站。第一组为特定的
(堆栈)创建匹配搜索
m
,状态为
=search。第一个团队具有
elo
(级别)属性。 当第二个团队(elo为150)搜索比赛时,我们执行以下查询:

SELECT m.id, m.value, m.teamOneScore, m.teamTwoScore, m.date, m.status, m.detail, m.team_one_id, m.team_two_id 
FROM user_match m
INNER JOIN team t ON m.team_one_id = t.id 
WHERE t.id = m.team_one_id 
    AND t.id <> 3        // You don't want to play against your own team
    AND t.elo <= 200     // 50 of elo range for example
    AND t.elo >= 100 
    AND m.value = '0.5'  
    AND m.status = 'search'
LIMIT 1
选择m.id、m.value、m.teamOneScore、m.teamTwoScore、m.date、m.status、m.detail、m.team\u one\u id、m.team\u two\u id
从用户_匹配m
在m.team\u one\u id=t.id上内部加入团队t
其中t.id=m.team\u one\u id
还有t.ID3//你不想和自己的球队比赛
t.elo=100
m.value='0.5'
m.status='search'
限制1
问题是,即使我们只有15000个user_match(只有40行用value=0.5、status=search回答需求)和15000个团队(有5570个团队用elo和id回答需求),这个查询也很长 我试图解释请求,结果如下:

如果用户搜索比赛时没有对手,请求可能需要大约3分钟,并且当同一请求多次执行时,这一时间将减少(缓存?),如果有对手,则速度会更快

我最不可能精确的一点是,user\u match表包含一个
detail
属性,该属性仅在匹配状态=end时才包含重json\u数组

你知道这是不是正常的执行时间吗?我能做些什么来改善这一点


谢谢

我认为您可以尝试为大多数被查询的列提供索引,就像当前where条件下的
列一样。


如果它们没有索引,那么您可以尝试“alter query向列添加索引”,然后查看响应时间。

直截了当地说,您需要使用in where子句为列编制索引

根据解释,mysql似乎计划只使用pk作为索引。您在where列中的pk仅用于排除单行。所以,mysql将扫描除单行之外的所有表

在这种情况下,您必须索引elo列,以使查询计划扫描最少的行

ALTER TABLE team ADD INDEX search(id, elo);
然后查看查询时间

+编辑 似乎上述解决方案并没有大大提高查询时间

还有一点。您需要先在join子句中放置较小的范围表。使用上述索引,团队表将更小。所以查询将如下所示

SELECT m.id, m.value, m.teamOneScore, m.teamTwoScore, m.date, 
       m.status, m.detail, m.team_one_id, m.team_two_id
FROM team t
INNER JOIN user_match m ON m.team_one_id = t.id 
WHERE 
t.elo <= 200     // 50 of elo range for example
AND t.elo >= 100
AND t.id <> 3        // You don't want to play against your own team
AND m.value = '0.5'  
AND m.status = 'search'
LIMIT 1
选择m.id、m.value、m.teamOneScore、m.teamTwoScore、m.date、,
m、 状态,m.detail,m.team\u一号,m.team\u二号
来自t队
内部连接用户\u匹配m.team\u one\u id=t.id上的m
哪里
t、 elo=100
还有t.ID3//你不想和自己的球队比赛
m.value='0.5'
m.status='search'
限制1

让我看看这是否适用于您。首先,不要重复
t.id=m.team\u one\u id
上的条件。因此,这是您的查询:

SELECT m.id, m.value, m.teamOneScore, m.teamTwoScore, m.date, m.status, m.detail, m.team_one_id, m.team_two_id 
FROM user_match m INNER JOIN
     team t
     ON m.team_one_id = t.id 
WHERE t.id <> 3 AND     // You don't want to play against your own team
      t.elo <= 200 AND    // 50 of elo range for example
      t.elo >= 100 AND
      m.value = '0.5' AND
      m.status = 'search'
LIMIT 1;
选择m.id、m.value、m.teamOneScore、m.teamTwoScore、m.date、m.status、m.detail、m.team\u one\u id、m.team\u two\u id
来自用户\u match m内部联接
t队
关于m.team\u one\u id=t.id
t.ID3和//你不想和自己的球队比赛
t、 elo=100和
m、 值='0.5'和
m、 状态='搜索'
限值1;
其次,查询看起来可疑,因为您有
限制
,没有
订单依据
。通常,您需要一个
ORDER BY
,以便保证每次执行时返回的行相同

索引是加速查询的方式。我将从以下索引开始:

  • 用户匹配(状态、价值、团队id)
  • 团队(id、elo)
根据
where
子句,
user\u match
上的索引是该表的最佳索引。注意:如果
value
是一个数字,则不要在
0.5
周围使用单引号,这可能会混淆优化器


如果将
id
声明为主键,
team
上的第二个索引是不必要的。

为什么在join子句中使用where子句时需要t.id=m.team\u one\u id(m.team\u one\u id=t.id上的内部join team t)?我认为这是多余的

我认为您应该移动ON子句中的团队过滤器,并获得如下内容

SELECT m.id, m.value, m.teamOneScore, m.teamTwoScore, m.date, m.status, m.detail, m.team_one_id, m.team_two_id 
FROM user_match m
INNER JOIN team t ON m.team_one_id = t.id and t.id <> 3 and t.elo <= 200 and t.elo >= 100
WHERE m.value = '0.5'  
    AND m.status = 'search'
LIMIT 1
以及上面评论中提到的团队表上的索引

ALTER TABLE team ADD INDEX elosearch_idx(id, elo);
请尝试这种方法。
如果这对我们没有帮助,请提供团队和用户匹配表的创建表,以便我们进一步调查。

我清除了mysql缓存,我尝试不使用索引。这花费了5.8秒(我不知道为什么,但速度比有时快),我在elo上创建了索引,花费了5.3秒。我在团队id上添加了索引,花了5.2秒,你认为这是这种查询的常规时间吗?现在我必须理解为什么有时候在team_one_id列上有索引或外键需要1分钟以上?我可以说这不是连接15000行的表的常规时间team_one_id是team table的外键其他人说你在重复where条件。您是否移除了它并看到了一些改进?谢谢您的回答!的确,它看起来很可疑,但我们知道,默认情况下,它应该按用户的匹配id排序,这就是我们想要的。关于重复的条件,这是一个错误,我试图索引用户匹配字段
status、value、team\u one\u id
,查询只需0.02秒(清除缓存后)!谢谢大家!@昆汀勒布。没有“默认”排序。SQL表和结果集表示无序集。如果您需要在结果集中进行排序,则需要使用排序依据。谢谢,我将使用排序依据来确定,但这并不是查找匹配项的重点。谢谢:)
ALTER TABLE team ADD INDEX elosearch_idx(id, elo);