许多行上运行计数和计数明显(数万)

时间:2012-10-02 22:55:58

标签: mysql

我正在尝试运行此查询:

SELECT 
    COUNT(events.event_id) AS total_events,
    COUNT(matches.fight_id) AS total_matches,
    COUNT(players.fighter_id) AS total_players,
    COUNT(DISTINCT events.organization) AS total_organizations,
    COUNT(DISTINCT players.country) AS total_countries
FROM 
    events, matches, players

这些是表格详细信息: 事件= 21k 球员= 90k 匹配= 155k

所有这些都是独一无二的,因此查询的前三个内容将是这些数字。其他两个值应该是total_organizations,其中组织列在事件中(应该返回几百个),total_countries应该使用players表中的country列(也是几百个)计算不同的国家。

所有这三个ID列都是唯一的并且已编入索引。

现在这个查询需要永远。我从来没有耐心看到它完整。有更快的方法吗?

另外,我需要这个在每个页面加载时加载这些结果,所以我应该把这个查询放在一些隐藏文件中,并设置一个cron作业来运行每个午夜或者其他东西并填充“总计”表或者其他东西我可以快速从那个表中检索它吗?

谢谢!

1 个答案:

答案 0 :(得分:1)

首先,删除不必要的连接;它阻止了大多数(如果不是全部)索引被使用。您需要三个不同的查询:

SELECT 
    COUNT(events.event_id) AS total_events,
    COUNT(DISTINCT events.organization) AS total_organizations
FROM 
    events;

SELECT 
    COUNT(matches.fight_id) AS total_matches
FROM 
    matches;

SELECT 
    COUNT(players.fighter_id) AS total_players,
    COUNT(DISTINCT players.country) AS total_countries
FROM 
    players;

这对提高这些查询的性能有很大帮助。

现在,考虑添加这些索引:

CREATE INDEX "events_organization" ON events (organization);
CREATE INDEX "players_country" ON events (country);

比较添加这些索引之前和之后的EXPLAIN SELECT ...结果。他们可能会有所帮助,也可能不会。


请注意,如果您使用的是InnoDB存储引擎,那么无论如何都会访问所有表行,以强制执行事务隔离。在这种情况下,索引仅用于确定要访问的表行。由于您在计算整个表,因此根本不会使用索引。

如果您使用的MyISAM不完全支持MVCC,那么COUNT()查询应该只能使用索引基数来执行,这将导致几乎即时的结果。这是可能的,因为MyISAM不支持事务,这意味着隔离变为无问题。

因此,如果您正在使用InnoDB,那么您最终可能不得不使用cronjob来创建此数据的缓存。