2017-08-01 223 views
-3

查詢到1分鐘,取結果MySQL查詢花費過多時間

SELECT 
`jp`.`id`, 
`jp`.`title` AS game_title, 
`jp`.`game_type`, 
`jp`.`state_abb` AS game_state, 
`jp`.`location` AS game_city, 
`jp`.`zipcode` AS game_zipcode, 
`jp`.`modified_on`, 
`jp`.`posted_on`, 
`jp`.`game_referal_amount`, 
`jp`.`games_referal_amount_type`, 
`jp`.`status`, 
`jp`.`is_flaged`, 
`u`.`id` AS employer_id, 
`u`.`email` AS employer_email, 
`u`.`name` AS employer_name, 
`jf`.`name` AS game_function, 
`jp`.`game_freeze_status`, 
`jp`.`game_statistics`, 
`jp`.`ats_value`, 
`jp`.`integration_id`, 
`u`.`account_manager_id`, 
`jp`.`model_game`, 
`jp`.`group_id`, 
(CASE 
    WHEN jp.group_id != '0' THEN gm.group_name 
    ELSE 'NA' 
END) AS group_name, 
`jp`.`priority_game`, 
(CASE 
    WHEN jp.country != 'US' THEN jp.country_name 
    ELSE '' 
END) AS game_country, 
IFNULL((CASE 
      WHEN 
       `jp`.`account_manager_id` IS NULL 
        OR `jp`.`account_manager_id` = 0 
      THEN 
       (SELECT 
         (CASE 
           WHEN 
            account_manager_id IS NULL 
             OR account_manager_id = 0 
           THEN 
            `u`.`account_manager_id` 
           ELSE account_manager_id 
          END) AS account_manager_id 
        FROM 
         user_user 
        WHERE 
         id = (SELECT 
           user_id 
          FROM 
           game_user_assigned 
          WHERE 
           game_id = `jp`.`id` 
          LIMIT 1)) 
      ELSE `jp`.`account_manager_id` 
     END), 
     `u`.`account_manager_id`) AS acc, 
(SELECT 
     COUNT(recach_limit_id) 
    FROM 
     recach_limit 
    WHERE 
     recach_limit = '1' 
      AND recach_limit_game_id = rpr.recach_limit_game_id) AS somewhatgame, 
(SELECT 
     COUNT(recach_limit_id) 
    FROM 
     recach_limit 
    WHERE 
     recach_limit = '2' 
      AND recach_limit_game_id = rpr.recach_limit_game_id) AS verygamecommitted, 
(SELECT 
     COUNT(recach_limit_id) 
    FROM 
     recach_limit 
    WHERE 
     recach_limit = '3' 
      AND recach_limit_game_id = rpr.recach_limit_game_id) AS notgame, 
(SELECT 
     COUNT(joa.id) AS applicationcount 
    FROM 
     game_refer_to_member jrmm 
      INNER JOIN 
     game_refer jrr ON jrr.id = jrmm.rid 
      INNER JOIN 
     game_applied joa ON jrmm.id = joa.referred_by 
    WHERE 
     jrmm.STATUS = '1' 
      AND jrr.referby_user_id IN (SELECT 
       ab_testing_user_id 
      FROM 
       ab_testing) 
      AND joa.game_post_id = rpr.recach_limit_game_id 
      AND (rpr.recach_limit = 1 
      OR rpr.recach_limit = 2)) AS gamecount 
FROM 
(`game_post` AS jp) 
    JOIN 
`user_info` AS u ON `jp`.`user_user_id` = `u`.`id` 
    JOIN 
`game_functional` jf ON `jp`.`game_functional_id` = `jf`.`id` 
    LEFT JOIN 
`group_musesm` gm ON `gm`.`group_id` = `jp`.`group_id` 
    LEFT JOIN 
`recach_limit` rpr ON `jp`.`id` = `rpr`.`recach_limit_game_id` 
WHERE 
`jp`.`status` != '3' 
GROUP BY `jp`.`id` 
ORDER BY `posted_on` DESC 
LIMIT 10 
+1

這是一個醜陋的查詢,對我來說這並不令人感到意外,它會很慢。在開始時添加一個'EXPLAIN'來提供信息輸出,然後進行相應的優化。從索引開始。 – ceejayoz

回答

0

我首先建議不要嵌套select語句,因爲這將導致在每個第x級的n^x的性能損失,我看到至少在這個查詢中選擇3個級別。

0

添加索引

INDEX(status, posted_on) 

移動LIMIT內

然後,而不是說

FROM (`game_post` AS jp) 

FROM (SELECT id FROM game_post 
      WHERE status != 3 
      ORDER BY posted_on DESC 
      LIMIT 10) AS ids 
JOIN game_post AS jp USING(id) 

(我假設jp的PK是(id)?)

這應該有效地使用新索引來獲得所需的10個ID。然後它會回到game_post來獲取其他列。

LEFT

另外,不要說LEFT,除非你需要它。它會產生一些東西來產生你可能不需要的NULLs

GROUP BY是否必要?

如果您刪除GROUP BY,它是否顯示dup id?上述變化可能已經消除了這個需要。

IN(SELECT)可以優化不佳

變化

AND jrr.referby_user_id IN (SELECT ab_testing_user_id 
           FROM ab_testing) 

AND EXISTS (SELECT * FROM ab_testing 
         WHERE ab_testing_user_id = jrr.referby_user_id) 

(這種變化可能會或可能不會幫助,這取決於你正在運行的版本。 )

更多

如果您需要更多幫助,請提供EXPLAIN SELECT