0

私はこのクエリを実行しようとしています:

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

表の詳細は次のとおりです。イベント=21,000人のプレーヤー=90kの試合=155k

これらはすべて一意であるため、クエリの最初の3つはそれらの数値になります。他の2つの値はtotal_organizationsである必要があります。ここで、組織列はイベントにあり(数百を返す必要があります)、total_countriesは、プレーヤーテーブルのcountry列を使用して個別の国をカウントする必要があります(これも数百)。

これらの3つのID列はすべて一意であり、インデックスが付けられています。

現在のこのクエリは永遠にかかります。私はそれが完了するのを見るのに我慢することさえありません。これを行うより速い方法はありますか?

また、ページを読み込むたびにこれらの結果を読み込むためにこれが必要なので、このクエリを隠しファイルに入れて、cronジョブを設定して、深夜などに実行し、「合計」テーブルなどにデータを入力して、取得できるようにする必要があります。そのテーブルからすぐに?

ありがとう!

4

1 に答える 1

1

まず、ここで不要な結合を削除します。これにより、ほとんどの(すべてではないにしても)インデックスが使用されなくなります。3つの異なるクエリが必要です。

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ストレージエンジンを使用している場合は、トランザクションの分離を強制するために、とにかくすべてのテーブル行にアクセスすることに注意してください。この場合、インデックスは、アクセスするテーブル行を決定するためにのみ使用されます。テーブル全体をカウントしているため、インデックスはまったく使用されません。

MVCCを完全にサポートしていないMyISAMを使用している場合は、COUNT()インデックスカーディナリティのみを使用してクエリを実行できる必要があります。これにより、ほぼ瞬時に結果が得られます。これが可能なのは、トランザクションがMyISAMでサポートされていないためです。つまり、分離は問題になりません。

したがって、InnoDBを使用している場合は、とにかくこのデータのキャッシュを作成するためにcronジョブを使用する必要が生じる可能性があります。

于 2012-10-02T23:01:21.367 に答える