帮助加快MySql查询速度

时间:2011-03-07 02:13:25

标签: php mysql sql

我如何加快这个mysql查询?

   SET @rank = 0;  

  UPDATE dbTable 
     SET rank_fd = @rank := @rank + 1 
ORDER BY fd2 DESC, fd3 DESC;

此查询更新~300,000个表行。它只需要太长时间....简单的控制面板(涡轮增压面板?)说mysqld只使用8-9%的CPU。我知道这总是如此,但这个查询在我的Core i7机器上花费的时间差不多。我认为我的P4专用服务器需要大约5-10分钟...这不会是一个问题,除非我不得不为不同的值做多次。它还使得其他mysql操作极其缓慢(几乎挂起),这极大地影响了网站性能。

软件:

  • CentOS版本5.4(最终版),
  • 简单控制面板版本1.4.8,
  • PHP 5.2.16
  • MySQL客户端版本:5.1.52

硬件:

  • Intel Pentium 4 CPU 3.0GHz
  • 2GB Ram

更多信息(2011年3月6日美国中部时间下午10点06分):

//Core i7 920 @ 2.6GHz, 6GB Ram
UPDATE dbTable SET rank_fd =999999999;
#275037 row(s) affected. ( Query took 7.0708 sec )

SET @rank =0;
#Your SQL query has been executed successfully ( Query took 0.0003 sec )

UPDATE dbTable SET rank_fd = @rank := @rank +1 ORDER BY fd2 DESC, fd3 DESC ;
#275037 row(s) affected. ( Query took 9.9931 sec )



//P4 3.0GHz, 2GB Ram
UPDATE dbTable SET rank_fd =999999999;
#Affected rows: 291468 (Query took 8.2165 sec)

SET @rank =0;
#Your SQL query has been executed successfully (Query took 0.0002 sec)

UPDATE dbTable SET rank_fd = @rank := @rank +1 ORDER BY fd2 DESC, fd3 DESC ;
#Affected rows: 291469 (Query took 305.2104 sec)  

更多信息(2011年3月7日下午6:37 CST):

我有一些新信息。如果我在P4上做一个select语句:

SET @rank =0;
SELECT @rank := @rank +1 AS rank_fd FROM dbTable ORDER BY fd2 DESC, fd3 DESC LIMIT 0, 300000;  
#Showing rows 0 - 29 (292,437 total, Query took 3.0448 sec)

计算一切只需3秒钟。无计量批量更新语句仅需8秒。正在进行的所有额外工作是什么导致它在我的原始声明中超过300秒。有没有办法在不涉及PHP的select calc语句之后捕获更新。我只是这样说,因为如果我在PHP中循环它,它将比原始语句花费更长的时间。

感谢迄今为止的所有帮助!!!

2 个答案:

答案 0 :(得分:3)

你正在修改表格中的每一行,当然它会很慢。根据{{​​1}}的使用方式,您可以在rank_fdfd2上放置索引并在运行时计算排名。

答案 1 :(得分:0)

您可以使用存储过程和临时表来加快排名过程。

以下示例使用一个玩家得分表,其中包含150万行,500个玩家得分超过3轮(500K * 3),并更新第1轮(500K行)的排名。 5秒。

希望这会有所帮助:)

示例表和存储过程

drop table if exists player_scores;
create table player_scores
(
round_id smallint unsigned not null,
player_id int unsigned not null,
score_1 int unsigned not null default 0,
score_2 int unsigned not null default 0,
rank int unsigned not null default 0,
primary key (round_id, player_id)
)
engine=myisam;

drop procedure if exists update_player_score_ranking;

delimiter #
create procedure update_player_score_ranking
(
p_round_id smallint unsigned
)
begin

  create table tmp_player_scores engine=memory select 
    round_id, player_id, score_1, score_2, @rank:= @rank + 1 as rank
  from 
    player_scores 
  inner join (select @rank:=0) r
  where
   round_id = p_round_id
  order by 
    score_1 desc, score_2 desc;

  delete from player_scores where round_id = p_round_id;
  insert into player_scores select * from tmp_player_scores;

  drop table if exists tmp_player_scores;

end #

delimiter ;

测试结果:

select count(*) from player_scores;
+----------+
| count(*) |
+----------+
|  1500000 |
+----------+
1 row in set (0.00 sec)

select count(*) from player_scores where round_id = 1;
+----------+
| count(*) |
+----------+
|   500000 |
+----------+
1 row in set (0.07 sec)

select * from player_scores where round_id = 1 order by score_1 desc, score_2 desc limit 5;
+----------+-----------+---------+---------+------+
| round_id | player_id | score_1 | score_2 | rank |
+----------+-----------+---------+---------+------+
|        1 |    456937 |   65534 |   49579 |    0 |
|        1 |     72439 |   65534 |   44537 |    0 |
|        1 |     16427 |   65534 |   43045 |    0 |
|        1 |    259871 |   65534 |   32095 |    0 |
|        1 |    324702 |   65534 |   15227 |    0 |
+----------+-----------+---------+---------+------+
5 rows in set (0.71 sec)


call update_player_score_ranking(1);
Query OK, 0 rows affected (5.57 sec)

select * from player_scores where round_id = 1 order by rank limit 5;
+----------+-----------+---------+---------+------+
| round_id | player_id | score_1 | score_2 | rank |
+----------+-----------+---------+---------+------+
|        1 |    456937 |   65534 |   49579 |    1 |
|        1 |     72439 |   65534 |   44537 |    2 |
|        1 |     16427 |   65534 |   43045 |    3 |
|        1 |    259871 |   65534 |   32095 |    4 |
|        1 |    324702 |   65534 |   15227 |    5 |
+----------+-----------+---------+---------+------+
5 rows in set (1.29 sec)