具有多个IF条件的查询优化,在mysql查询中使用ORDER BY

时间:2013-12-13 10:17:16

标签: mysql query-optimization

我有以下查询

  SELECT wit_games.id          AS gameId, 
       wit_games.turn_count, 
       wit_users.id            AS opponentId, 
       wit_users.username      AS name, 
       wit_users.login_section, 
       wit_users.image, 
       wit_users.email, 
       Ifnull( (SELECT 
                    IF( wit_game_turns.user_id = 911,  
                        IF(wit_game_turns.status = 1, 2, 3), 
                        IF(wit_game_turns.status = 1, 4, 1))
                FROM   wit_game_turns 
                WHERE  wit_game_turns.game_id = wit_games.id 
                ORDER  BY wit_game_turns.id DESC 
                LIMIT  0, 1
           ), 
           IF(wit_games.participant1 = 911, 1, 3)
       ) AS turnSts 
FROM   wit_games 
LEFT JOIN wit_users 
       ON wit_users.id = 
              IF(wit_games.participant1 = 911, wit_games.participant2, 
                 wit_games.participant1) 
WHERE  wit_games.status = 1 
       AND ( wit_games.participant1 = 911 
              OR wit_games.participant2 = 911 ) 
ORDER  BY turnsts DESC, 
          wit_users.login_sts DESC, 
          wit_games.id 
LIMIT  0, 100 

此查询需要5秒钟才能执行。 EXPLAIN 会给出以下结果

    id  select_type     table   type    possible_keys   key     key_len     ref     rows    Extra
1   PRIMARY     wit_games   index_merge     participant1,participant2   participant1,participant2   4,4     NULL    664     Using union(participant1,participant2); Using wher...
1   PRIMARY     wit_users   eq_ref  PRIMARY,id_2    PRIMARY     4   func    1   
2   DEPENDENT SUBQUERY  wit_game_turns  index   game_id     PRIMARY     4   NULL    1   Using where rows    Extra
1   PRIMARY     wit_games   index_merge     participant1,participant2   participant1,participant2   4,4     NULL    664     Using union(participant1,participant2); Using wher...
1   PRIMARY     wit_users   eq_ref  PRIMARY,id_2    PRIMARY     4   func    1   
2   DEPENDENT SUBQUERY  wit_game_turns  index   game_id     PRIMARY     4   NULL    1   Using where

我为用户名,电子邮件,参与者1,参与者2,game_id建立了索引。

如何优化此查询以获得更好的效果。

表结构如下

wit_games

 Column         Type        
id          int(11)     
participant1    int(11)     
participant2    int(11)     
game_date   datetime        
turn            int(11)     
turn_count  int(11)     
lang_id         int(11)     
status         smallint(1)

wit_users

Column    Type      
id            int(11)       
login_section int(2)        
fb_id   bigint(200)     
access_token    text        
gcmId   varchar(200)        
deviceTocken    varchar(1000)       
email   varchar(50)     
username    varchar(50)     
password    varchar(150)        
image   varchar(500)        
status  int(2)      
login_sts   smallint(1)     
loggedInDevice  int(2)      
points  float       
lang_id int(11)     
badge   int(11) 

wit_games_turns

Column  Type        
id  int(11)     
game_id int(11)     
text_id int(11)     
video   longblob        
user_id int(11)     
reply_user_id   int(11)     
reply_text  varchar(100)        
points  float       
has_bonus   int(2)      
added_date  datetime        
status  smallint(1) 

提前致谢..

1 个答案:

答案 0 :(得分:0)

我试图优化您的查询。你可以测试它是否正常工作。 如果你提供一些样本数据会更好。

SELECT 
    wu.id                                           AS opponentId, 
    wu.username                                     AS name, 
    wu.login_section, 
    wu.image, 
    wu.email, 
    wg.id,
    wg.turn_count, 
    IFNULL(wg.participant1,wg.participant) turnSts
FROM wit_users wu
LEFT JOIN (
    SELECT 
        wit_games.id,
        wit_games.turn_count,
        IF(participant1 = 911, 1, 3) participant,
        IF(wgt.user_id = 911, IF(wgt.status = 1, 2, 3), IF(wgt.status = 1, 4, 1)) participant1
    FROM wit_games
    INNER JOIN  wit_game_turns wgt ON wgt.game_id = wit_games.id
    WHERE status = 1 
    AND 911 IN (participant1,participant2)
) AS wg ON wg.participant_id = wu.id
ORDER  BY turnsts DESC, wu.login_sts DESC, wg.id 
LIMIT  0, 100