MySQL服务器在执行简单查询后挂起

时间:2015-03-18 13:48:52

标签: php mysql phpmyadmin server

我在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

2 个答案:

答案 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);

请参阅小提琴:http://sqlfiddle.com/#!9/72444/1