MySql-糟糕的表现

时间:2018-06-29 22:32:46

标签: mysql

我正在尝试对具有五百万行的表运行相对简单的查询。这只是我用来测试返回的值正确的一个小片段。问题在于此查询需要花费20分钟以上的时间才能完成,即使对于500,000条记录而言,这似乎也异常缓慢。

DROP VIEW IF EXISTS view_temp_sortie_stats;
CREATE VIEW view_temp_sortie_stats AS
SELECT server_id, session_id, ucid, role, sortie_id, 
    (
        SELECT COUNT(sortie_id)
        FROM raw_gameevents_log 
        WHERE sortie_id = l.sortie_id AND server_id = l.server_id AND session_id = l.session_id AND target_player_ucid = l.ucid AND event = "HIT"
    ) AS HitsReceived
FROM raw_gameevents_log l
WHERE ucid IS NOT NULL AND sortie_id IS NOT NULL
GROUP BY server_id, session_id, ucid, role, sortie_id;

SELECT * FROM view_temp_sortie_stats;

这是我的桌子:

table

接下来,我尝试为server_id,session_id,sortie_id添加索引以查看它是否会改进-这花费了超过10分钟的时间,并且超时。所以我无法添加它们。

这似乎异常缓慢,应该不需要花费太多时间来添加索引或执行此查询。

我的innodb_buffer_pool_size是5GB,但是运行这些查询时mysqld进程仅消耗300mb的内存。

我在具有12 GB Ram,2倍Intel Haswell CPU的Windows Server 2012 R2 Standard上运行,因此我应该从mysql那里看到比这更好的性能。

没有其他人连接到该MySql实例,并且没有其他操作发生。

EDIT -这是解释的查询 enter image description here

有人知道出什么问题吗?

EDIT2 -部分修复

经过一番谷歌搜索后,我发现了为什么添加索引会永远占用-原始查询仍在后台运行了2个小时以上。一旦我杀死了查询,添加索引就花费了大约30秒。

现在,当我运行上面的查询时,它需要27秒-可以肯定的是,这是一个巨大的改进,但是对于500,000条记录而言,这仍然相当缓慢。这是新的查询说明计划:

enter image description here

1 个答案:

答案 0 :(得分:1)

您的子查询是:

    SELECT COUNT(sortie_id)
    FROM raw_gameevents_log 
    WHERE sortie_id = l.sortie_id AND server_id = l.server_id 
    AND session_id = l.session_id AND target_player_ucid = l.ucid 
    AND event = "HIT"

,主要查询是:

SELECT server_id, session_id, ucid, role, sortie_id, [...]
FROM raw_gameevents_log l
WHERE ucid IS NOT NULL AND sortie_id IS NOT NULL
GROUP BY server_id, session_id, ucid, role, sortie_id;

让我们从子查询开始。 COUNT可以依靠任何东西,因此我们不必理会选择字段。 WHERE字段:

    WHERE sortie_id = l.sortie_id AND server_id = l.server_id 
    AND session_id = l.session_id AND target_player_ucid = l.ucid 
    AND event = "HIT"

您创建一个从常量字段开始的索引,然后是其他字段:

CREATE INDEX subqindex ON raw_gameevents_log(
    event,
    sortie_id, server_id, session_id, target_player_ucid
)

然后是主要查询:

WHERE ucid IS NOT NULL AND sortie_id IS NOT NULL
GROUP BY server_id, session_id, ucid, role, sortie_id;

这里您需要一个索引

ucid, sortie_id, server_id, session_id, role

最后,您可以尝试摆脱子查询(即使优化器可能已经对此做了很好的工作):

SELECT server_id, session_id, ucid, role, sortie_id, 
COALESCE(hits, 0) AS hits
FROM raw_gameevents_log l
LEFT JOIN 
(
    SELECT COUNT(1) AS hits FROM raw_gameevents_log
    WHERE event = 'HIT'
) AS h
ON (h.sortie_id = l.sortie_id, h.server_id = l.server_id, h.session_id = l.session_id, h.target_player_ucid = l.ucid)
WHERE l.ucid IS NOT NULL AND l.sortie_id IS NOT NULL
GROUP BY l.server_id, l.session_id, l.ucid, l.role, l.sortie_id;