我正在尝试运行此查询:
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作业来运行每个午夜或者其他东西并填充“总计”表或者其他东西我可以快速从那个表中检索它吗?
谢谢!
答案 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来创建此数据的缓存。