我在ARM机器上运行了一个MySQL服务器,我有一个查询在phpmyadmin
通过网络界面(或网站上的php)运行
select * from some_table where id IN (select id from other_table)
这个简单的查询将导致MySQL服务挂起,直到重新启动。 是什么原因?
换句话说:
如果我手动输入id - 是1或100 - 它不会失败:
select * from some_table where id IN (1,2,3,4,5,6,7,8,9....120)
另一方面 - 如果id是从内部查询生成的,那么服务将挂起:
select * from some_table where id IN (select id from other_table)
我可以完全访问服务器,并且可以根据需要重新配置它。请帮助我提供有关如何解决问题的建议。
数据库服务器
服务器:通过UNIX套接字的Localhost
服务器类型:MySQL
服务器版本:5.5.35-1ubuntu1 - (Ubuntu)
协议版本:10
用户:root @ localhost
服务器字符集:UTF-8 Unicode(utf8)
网络服务器
的nginx / 1.4.6
数据库客户端版本:libmysql - 5.5.35
PHP扩展:mysqli
成功运行
版本信息:4.0.10deb1
P.S。悬挂的意思是mysql
没有反应。命令top
将显示MySQL服务占用了所有内核。通过命令sudo /etc/init.d/mysql restart
重新启动。
P.P.S。挂起的完整查询。小提琴:http://sqlfiddle.com/#!9/84fe8/1
select
goo.t1_score,
goo.t2_score,
gr.t1_score,
gr.t2_score,
gr.unique_key
from games_ongoing goo, game_results gr
where
goo.id in (
select max(id)
from games_ongoing
group by unique_key
having count(id) >= 3 and MIN(t1_score) = MIN(t2_score) and MIN(t1_score) = 0
)
and gr.unique_key = goo.unique_key
答案 0 :(得分:0)
所以,回顾一下......这是一个中间结果
SELECT o.id o_id
, o.t1_score o_t1_score
, o.t2_score o_t2_score
, r.t1_score r_t1_score
, r.t2_score r_t2_score
, r.unique_key
FROM games_ongoing o
JOIN game_results r
ON r.unique_key = o.unique_key;
+------+------------+------------+------------+------------+------------+
| o_id | o_t1_score | o_t2_score | r_t1_score | r_t2_score | unique_key |
+------+------------+------------+------------+------------+------------+
| 1 | 0 | 0 | 1 | 3 | 111 |
| 2 | 0 | 1 | 1 | 3 | 111 |
| 3 | 0 | 2 | 1 | 3 | 111 |
| 4 | 1 | 2 | 1 | 3 | 111 |
| 5 | 1 | 2 | 1 | 3 | 111 |
| 6 | 0 | 0 | 5 | 4 | 222 |
| 7 | 1 | 1 | 5 | 4 | 222 |
| 8 | 2 | 1 | 5 | 4 | 222 |
+------+------------+------------+------------+------------+------------+
为了获得具有最高(正在进行的)id的唯一键,我们可以使用不相关的子查询,如下所示:
SELECT x.*
, r.*
FROM games_ongoing x
JOIN
( SELECT unique_key, MAX(id) max_id FROM games_ongoing GROUP BY unique_key ) y
ON y.unique_key = x.unique_key
AND y.max_id = x.id
JOIN game_results r
ON r.unique_key = x.unique_key;
+----+---------+---------+------------+----------+----------+----+----------+----------+------------+
| id | t1_name | t2_name | unique_key | t1_score | t2_score | id | t1_score | t2_score | unique_key |
+----+---------+---------+------------+----------+----------+----+----------+----------+------------+
| 5 | team1 | team2 | 111 | 1 | 2 | 1 | 1 | 3 | 111 |
| 8 | team3 | team4 | 222 | 2 | 1 | 2 | 5 | 4 | 222 |
+----+---------+---------+------------+----------+----------+----+----------+----------+------------+
这应该比上面的查询要好得多,但是为了进一步帮助优化这个,我们需要看看EXPLAIN。
答案 1 :(得分:0)
回答你原来的问题。在MySQL中,这个查询:
select * from some_table where id IN (select id from other_table)
将执行以下查询:
SELECT id
FROM other_table
WHERE other_table.id = some_table.id
为some_table
中的每条记录,而这一条记录为:
select * from some_table where id IN (1,2,3,4,5,6,7,8,9....120)
将从some_table
的列表中搜索每个值。如果some_table
上有很多记录,但other_table
中很少有记录,则应该像这样重写查询:
SELECT st.*
FROM (
SELECT DISTINCT
id
FROM other_table
) ot
JOIN some_table st
ON st.id = ot.id
将搜索other_table.id
上的索引中的每个不同some_table.id
。
现在,假设没有负分,您应该运行此查询:
SELECT *
FROM game_results gr
JOIN games_ongoing goo
ON goo.id =
(
SELECT id
FROM games_ongoing goi
WHERE goi.unique_key = gr.unique_key
AND EXISTS
(
SELECT NULL
FROM games_ongoing goz
WHERE goz.unique_key = goi.unique_key
AND (goz.t1_score, goz.t2_score) = (0, 0)
)
AND EXISTS
(
SELECT NULL
FROM games_ongoing goc
WHERE goc.unique_key = goi.unique_key
LIMIT 2, 1
)
ORDER BY
goi.unique_key DESC, goi.id DESC
LIMIT 1
)
为查询创建以下索引以使其快速运行:
CREATE INDEX ix_game_results_unique_key ON game_results (unique_key);
CREATE INDEX ix_games_ongoing_unique_key ON games_ongoing (unique_key);
CREATE INDEX ix_games_ongoing_unique_key_t2_score_t2_score ON games_ongoing (unique_key, t1_score, t2_score);