2017-06-02 13 views
0

少なくとも1つのレコードの存在を検出user_activitiesテーブルは非常に大きく、3億以上の行があります。のMySQL:</p> <p>ユーザ(ID、名前)</p> <p>user_activities(ID、USER_ID、ACTIVITY_ID、のcreated_at)</p> <p>:私は2つのテーブルを持っている大きな結合テーブル

特定の期間内にどのユーザーが何らかのアクティビティを実行したことを検出しようとしています。つまり、特定のcreated_atの範囲のuser_activitiesテーブルに結合された行が存在するユーザーテーブルの行。

INNER JOIN、GROUP BY、およびWHERE句でこれを行うことはできますが、私の日付範囲内のすべてのuser_activities行に当たると思われるので、クエリは長い時間実行されます。

私は本当に "何個"の活動を気にしません。だから実際に私はちょうど1を見つけた後に停止することができたときにカウントを取得するためにグループ化しています(例えば210アクティビティ)。

すべてのuser_activity行をグループ化するのではなく、これを行うより効率的な方法はありますか?詳細については

は、ここでは正常に動作しますが、長い時間がかかり、現在のクエリでは、です:事前に

SELECT u.id, u.name, COUNT(ua.id) AS activity_count 
FROM users u 
INNER JOIN user_activity ua ON u.id=ua.user_id 
WHERE ua.created_at > '2017-01-01' AND ua.created_at < '2017-03-01' 
GROUP BY u.id 
HAVING activity_count > 0; 

ありがとう!

+2

を返します。それ以外の、与えられた条件を満足するかどうか、これは単にコラム RET = 1 を返します。含まれています。 (つまり、activity_countは常に0より大きくなります) – jarlh

+0

したがって、COUNT(ua.id)も削除できますか? – infaddict

+0

ユーザーあたりのアクティビティ数をカウントする必要がありますか、ユーザーがアクティブである(つまり、日付範囲内に少なくとも1つのアクティビティがある)ことを知っていれば十分ですか? –

答えて

1

あなたは、このバージョンを試すことができます:パフォーマンスのために

SELECT u.id, u.name, 
     (SELECT COUNT(*) 
     FROM user_activity ua 
     WHERE u.id = ua.user_id AND 
       ua.created_at > '2017-01-01' AND 
       ua.created_at < '2017-03-01' 
     ) as activity_count 
FROM users u 
HAVING activity_count > 0; 

あなたはuser_activity(user_id, created_at)にインデックスをしたいです。

EDIT:

あなただけの存在にしたい場合は、同じインデックスを使用し、これははるかに高速でなければなりません:

SELECT u.id, u.name 
FROM users u 
WHERE EXISTS (SELECT 1 
       FROM user_activity ua 
       WHERE u.id = ua.user_id AND 
        ua.created_at > '2017-01-01' AND 
        ua.created_at < '2017-03-01' 
      ); 

クエリが複雑な処理やデータの束の、その後の集約を行うのに対し、これはusersテーブルをスキャンし、適切なアクティビティがユーザに存在するかどうかをインデックスで調べるだけです。

+0

ありがとう、ゴードン、あなたの2番目のクエリは、私が欲しいものです! – infaddict

+0

予測分析に関する作業の一部を見て、私はあなたがこれを掘り下げるかもしれないと考えました。 MITはAIについていくつかの講演をしている。少し遅く始まりますが、それは良くなります。 http://www.openculture.com/2017/05/artificial-intelligence-a-free-online-course-from-mit.html ... –

+0

@JohnCappelletti。 。 。学部生として、私はPatrick WinstonのMITでAIコースを受講しました。私は公開フォーラムでコメントしません;) –

1

EXISTS句を使用すると、DBMSは、指定された日付範囲内のユーザーあたり1レコードを検索すれば十分であると判断します。このインデックス付き

SELECT id, name 
FROM users u 
where exists 
(
    select * 
    from user_activity ua 
    where ua.user_id = u.id 
    and ua.created_at > '2017-01-01' AND ua.created_at < '2017-03-01' 
); 

create index idx on user_activity(user_id, created_at); 
0

その場合は、指定した日付範囲

select u.id, u.name from users u 
    where exists (SELECT 1 FROM user_activity ua 
     where ua.user_id = u.id 
     and ua.created_at > '2017-01-01' AND 
       ua.created_at < '2017-03-01') 

のための活動を行っているユーザーはuser_activityのインデックス(のcreated_at)

0

を作成しますするにはテストのためだけに:

SELECT EXISTS(
    SELECT u.id 
     FROM user_activity AS ua 
     WHERE u.id = ua.user_id 
      AND ua.created_at > '2017-01-01' 
      AND ua.created_at < '2017-03-01' 
) AS ret 

クエリの少なくとも行はそれがここで必要HAVING、活動なくして、ユーザーができなくなります列 RET = 0

関連する問題

 関連する問題