我正在尝试运行此查询:
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玩家=90000匹配=155k
所有这些都是unique,所以查询的前3个内容将是这些数字。另外两个值应该是total_organizations,其中组织列在事件中(应该返回几百),total_countries应该使用玩家表中的国家列来计算不同的国家(也是几百)。
这三个ID列都是唯一的,并且都有索引。
目前的这种查询需要很长时间。我甚至从来没有耐心看到它完成。有没有更快的方法?
此外,我需要它来在每次页面加载时加载这些结果,所以我应该把这个查询放在某个隐藏文件中,并设置一个cron作业,使其在每午夜或其他时间运行,并填充一个"总计"表或其他内容,这样我就可以快速从该表中检索它吗?
谢谢!
首先,删除此处不必要的联接;它阻止了大部分(如果不是全部的话)索引被使用。您想要三个不同的查询:
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来创建该数据的缓存。