【问题标题】:my query is causing mysqlid CPU to spike 99% usage, and i want to simplify the query我的查询导致 mysqlid CPU 使用率达到 99%,我想简化查询
【发布时间】:2014-02-21 03:32:44
【问题描述】:

这是我的查询

SELECT DISTINCT (game.game_id) 
AS gid, game_link.is_linked, game_link.game_id1, game_bet_settings.bet_type_id 
AS bet_type
FROM game
LEFT JOIN kiosk_to_game ON ( kiosk_to_game.game_id = game.game_id ) 
LEFT JOIN game_bet_settings ON ( game_bet_settings.game_id = game.game_id ) 
LEFT JOIN game_link ON ( game_link.game_id1 = game.game_id
OR game_link.game_id2 = game.game_id ) 
AND game.game_id !=  ''
AND game.game_winner =  '0'
AND game.game_open_bet_time <=  '2014-02-21 12:12:48'
AND game.game_close_bet_time >=  '2014-02-21 12:12:48'
AND kiyosuku_to_game.kiyosuku_id =  '1'
AND game.game_is_active =  '1'
AND game_bet_settings.is_disabled !=1
AND (game_link.is_linked IS NULL OR game_link.is_linked =1)
ORDER BY game.game_start_time ASC 

我认为罪魁祸首可能是:

SELECT DISTINCT (game.game_id) 
AS gid, game_link.is_linked, game_link.game_id1, game_bet_settings.bet_type_id 
AS bet_type

任何人都可以将此查询简化为更有效的查询吗?

这是 sql 进程的图像: https://lh5.googleusercontent.com/--BsUDk8jLnY/UwbKFiCjZCI/AAAAAAAAAi4/MXCQFhs4PeU/w496-h216-no/sqlquery.png

这是我的一些表索引:

游戏

PRIMARY - game_id

游戏链接

PRIMARY - game_link_id   
game_id1 - game_id1, game_id2

game_bet_settings

PRIMARY - game_bet_settings_id
game_id - game_id

【问题讨论】:

  • 你的索引是什么样的?
  • 你想要所有的表索引?还是只是一个特定的?
  • 已完成问题的编辑,希望对您有所帮助
  • 确保您还索引了kiosk_to_game.game_id。如果没有看到您使用的数据,真的很难猜测。我建议您尝试简化查询,直到找到导致减速的部分(例如,尝试不使用 order by,尝试仅使用一个连接并一次添加其他连接,等等)。按性能排序有时也可以be improved by indexes
  • thnx @CarlGroner,当我向 game_id 添加索引时,我的查询比旧查询快 100 倍

标签: mysql sql deadlock


【解决方案1】:

您可以尝试添加此索引:

game(game_winner, is_active, open_bet_time, close_bet_time, game_id);

但是,罪魁祸首可能是:

LEFT JOIN game_link ON ( game_link.game_id1 = game.game_id OR game_link.game_id2 = game.game_id ) 

or 的查询很难优化。

尝试在没有此条件的情况下运行您的查询:

SELECT DISTINCT (game.game_id) 
AS gid, game_link.is_linked, game_link.game_id1, game_bet_settings.bet_type_id 
AS bet_type
FROM game
LEFT JOIN kiosk_to_game ON ( kiosk_to_game.game_id = game.game_id ) 
LEFT JOIN game_bet_settings ON ( game_bet_settings.game_id = game.game_id ) 
LEFT JOIN game_link ON ( game_link.game_id1 = game.game_id ) 
AND game.game_id !=  ''
AND game.game_winner =  '0'
AND game.game_open_bet_time <=  '2014-02-21 12:12:48'
AND game.game_close_bet_time >=  '2014-02-21 12:12:48'
AND kiyosuku_to_game.kiyosuku_id =  '1'
AND game.game_is_active =  '1'
AND game_bet_settings.is_disabled !=1
AND (game_link.is_linked IS NULL OR game_link.is_linked =1)
ORDER BY game.game_start_time ASC 

如果这在合理的时间内有效,则尝试将两个查询合并在一起(每个条件一个)。

编辑:

联合看起来像:

(SELECT DISTINCT (game.game_id) 
 AS gid, game_link.is_linked, game_link.game_id1, game_bet_settings.bet_type_id 
 AS bet_type
 FROM game
 LEFT JOIN kiosk_to_game ON ( kiosk_to_game.game_id = game.game_id ) 
 LEFT JOIN game_bet_settings ON ( game_bet_settings.game_id = game.game_id ) 
 LEFT JOIN game_link ON ( game_link.game_id1 = game.game_id ) 
 AND game.game_id !=  ''
 AND game.game_winner =  '0'
 AND game.game_open_bet_time <=  '2014-02-21 12:12:48'
 AND game.game_close_bet_time >=  '2014-02-21 12:12:48'
 AND kiyosuku_to_game.kiyosuku_id =  '1'
 AND game.game_is_active =  '1'
 AND game_bet_settings.is_disabled !=1
 AND (game_link.is_linked IS NULL OR game_link.is_linked =1)
)
UNION
(SELECT DISTINCT (game.game_id) 
 AS gid, game_link.is_linked, game_link.game_id1, game_bet_settings.bet_type_id 
 AS bet_type
 FROM game
 LEFT JOIN kiosk_to_game ON ( kiosk_to_game.game_id = game.game_id ) 
 LEFT JOIN game_bet_settings ON ( game_bet_settings.game_id = game.game_id ) 
 LEFT JOIN game_link ON ( game_link.game_id2 = game.game_id ) 
 AND game.game_id !=  ''
 AND game.game_winner =  '0'
 AND game.game_open_bet_time <=  '2014-02-21 12:12:48'
 AND game.game_close_bet_time >=  '2014-02-21 12:12:48'
 AND kiyosuku_to_game.kiyosuku_id =  '1'
 AND game.game_is_active =  '1'
 AND game_bet_settings.is_disabled !=1
 AND (game_link.is_linked IS NULL OR game_link.is_linked =1)
)
ORDER BY game_start_time ASC

【讨论】:

  • 试过了,它仍然飙升。索引可能有问题
【解决方案2】:

我建议将查询放置条件重新组合到子查询以限制记录数量。

SELECT DISTINCT (game.game_id) 
AS gid, game_link.is_linked, game_link.game_id1, game_bet_settings.bet_type_id 
AS bet_type
FROM (select * from game
      where
         game.game_id !=  ''
         AND game.game_winner =  '0'
         AND game.game_open_bet_time <=  '2014-02-21 12:12:48'
         AND game.game_close_bet_time >=  '2014-02-21 12:12:48'
         AND game.game_is_active =  '1'
     )
LEFT JOIN kiosk_to_game ON ( kiosk_to_game.game_id = game.game_id ) 
LEFT JOIN game_bet_settings ON ( game_bet_settings.game_id = game.game_id ) 
LEFT JOIN game_link ON ( game_link.game_id1 = game.game_id
OR game_link.game_id2 = game.game_id ) 
AND kiyosuku_to_game.kiyosuku_id =  '1'
AND (game_link.is_linked IS NULL OR game_link.is_linked =1)
ORDER BY game.game_start_time ASC 

【讨论】:

  • 每个派生表都必须有自己的别名
猜你喜欢
  • 2018-03-18
  • 1970-01-01
  • 2021-02-28
  • 2013-12-15
  • 2021-12-29
  • 2012-02-05
  • 1970-01-01
  • 2020-10-08
  • 2023-04-03
相关资源
最近更新 更多