1

これが私のクエリです:

SELECT SQL_BUFFER_RESULT SQL_BIG_RESULT users.id, users.email, 
        COUNT(av.user_id) AS article_views_count,
        COUNT(af.id) AS article_favorites_count,
        COUNT(lc.user_id) AS link_clicks_count,
        COUNT(ai.user_id) AS ad_impressions_count,
        COUNT(ac.user_id) AS ad_clicks_count
          FROM users
            LEFT JOIN article_views AS av     ON (av.user_id = users.id AND av.created_at >= '2012-11-28 00:00:00' AND av.created_at <= '2012-11-30 23:59:59')
            LEFT JOIN article_favorites AS af ON (af.user_id = users.id AND af.created_at >= '2012-11-28 00:00:00' AND af.created_at <= '2012-11-30 23:59:59')
            LEFT JOIN link_clicks AS lc       ON (lc.user_id = users.id AND lc.created_at >= '2012-11-28 00:00:00' AND lc.created_at <= '2012-11-30 23:59:59')
            LEFT JOIN ad_impressions AS ai    ON (ai.user_id = users.id AND ai.created_at >= '2012-11-28 00:00:00' AND ai.created_at <= '2012-11-30 23:59:59')
            LEFT JOIN ad_clicks AS ac         ON (ac.user_id = users.id AND ac.created_at >= '2012-11-28 00:00:00' AND ac.created_at <= '2012-11-30 23:59:59')
          GROUP BY users.id
          HAVING (article_views_count + article_favorites_count + link_clicks_count + ad_impressions_count + ad_clicks_count) > 0

コンテキストを提供するいくつかの統計:

  1. ユーザー: 1,474,348 行
  2. article_views: 32,603,637 行
  3. article_favorites: 10,199 行
  4. link_clicks: 4,258,901 行
  5. ad_impressions: 66,758,573 行
  6. ad_clicks: 324,125 行

結合されたすべてのテーブルには、user_id と created_at (この順序で) に複合インデックスがあります。

Mysql 5 を実行しています。すべてのテーブルは MyISAM エンジンです。

クエリの EXPLAIN は次のとおりです: https://gist.github.com/4197482

目標は、期間内に何らかのアクティビティ (表示、お気に入り、クリック、インプレッション、広告クリック) を行ったユーザーのみを返すことです。

この悪い子を最適化するためのアイデアはありますか?

4

2 に答える 2

1

あなたのクエリは、大量のデータに基づいて分析を行うための分析クエリのようです(集計関数と GROUP BY 句が含まれているため)。

このようなクエリのパフォーマンスを向上させるには、マテリアライズド ビューの結果を作成し、次のような方法で JOIN を作成できます。

CREATE TABLE my_view AS SELECT ... FROM ... JOIN ...

そうすることで、MySQL は集計を計算するだけで済むため、次のクエリははるかに効率的になります。

次に、テーブルを更新するための戦略を実装する必要があります(たとえば、タイムスタンプを介して)

別の解決策は、この種のクエリで効率的に構築された DBMS (列指向データベース) にデータをインポートすることです。たとえば、分析クエリ用に最適化されたストレージ エンジンを備えた MySQL ベースのオープン ソース dbms である InfiniDB です。

于 2012-12-03T20:16:11.537 に答える
0

クエリをINNER JOIN各テーブルで分割し、それらを で結合してみてくださいUNION。お気に入り

SELECT users.id, users.email, COUNT(av.user_id) AS article_views_count
FROM users
JOIN article_views AS av ON (av.user_id = users.id AND av.created_at >= '2012-11-28 00:00:00' AND av.created_at <= '2012-11-30 23:59:59')
GROUP BY users.id, users.email

UNION

....
于 2012-12-03T19:53:09.677 に答える