うまくいっていることを願っています。
このデータベースについて少し助けが必要です:
これは、投票を格納するデータベースです。ユーザーは好きなオーディオ トラックを選び、投票します。彼らは「上」または「下」に投票できます。やさしい。しかし、計算統計に関しては、毛むくじゃらになります。
メタ
これは、最も一般的に使用される統計 (キャッシングのようなもの) を格納するキー値スタイルのテーブルです。
mysql> SELECT * FROM Meta;
+-------------+-------+
| Key | Value |
+-------------+-------+
| TRACK_COUNT | 2620 |
| VOTE_COUNT | 3821 |
| USER_COUNT | 371 |
+-------------+-------+
投票
投票テーブルは、投票自体を保持します。ここで唯一興味深いフィールドはType
, の値で、次のことを意味します。
0
- アプリは投票を行い、ユーザーはUIを使用してトラックに投票しました1
- インポートされた投票 (外部サービスから)2
- 統合投票。実際にはインポートされた投票と同じですが、実際には、このユーザーは外部サービスを使用してこのトラックに既に投票されており、現在はアプリを使用して自分自身を繰り返していることを示しています。
追跡
トラックは、それ自体の合計統計を保持します。好き、嫌いの量、外部サービスからの好き ( LikesRP
)、外部サービスからの嫌い ( DislikesRP
)、好き嫌いの調整。
アプリ
アプリは次の投票を取得する必要があります。
- 過去 7 日間で最も投票数が多かった 5 つのトラック
- 過去 7 日間で最も反対票が多かった 5 つのトラック
- 過去 7 日間で最も高く評価された 5 つのトラック。その投票は外部サービスからインポートされました (
Vote.Type = 1
) - 過去 1 か月間で最も投票数が多かった 100 曲
上位 100 位のトラックを取得するには、次のクエリを使用します。
SELECT
T.Hash,
T.Title,
T.Artist,
COALESCE(X.VotesTotal, 0) + T.LikesAdjust as VotesAdjusted
FROM (
SELECT
V.TrackHash,
SUM(V.Vote) AS VotesTotal
FROM
Vote V
WHERE
V.CreatedAt > NOW() - INTERVAL 1 MONTH AND V.Vote = 'up'
GROUP BY
V.TrackHash
ORDER BY
VotesTotal DESC
) X
RIGHT JOIN Track T
ON T.Hash = X.TrackHash
ORDER BY
VotesAdjusted DESC
LIMIT 0, 100;
このクエリは正常に機能しており、調整を受け入れています (クライアントはリスト内のトラック位置を調整したいと考えていました)。ほぼ同じクエリを使用して、賛成/反対の投票数が最も多い 5 つのトラックを取得します。タスク #3 のクエリは次のとおりです。
SELECT
T.Hash,
T.Title,
T.Artist,
COALESCE(X.VotesTotal, 1) as VotesTotal
FROM (
SELECT
V.TrackHash,
SUM(V.Vote) AS VotesTotal
FROM
Vote V
WHERE
V.Type = '1' AND
V.CreatedAt > NOW() - INTERVAL 1 WEEK AND
V.Vote = 'up'
GROUP BY
V.TrackHash
ORDER BY
VotesTotal DESC
) X
RIGHT JOIN Track T
ON T.Hash = X.TrackHash
ORDER BY
VotesTotal DESC
LIMIT 0, 5;
問題は、最初のクエリの実行に約 2 秒かかり、投票数が 4,000 未満であることです。年末までに、この数字は約 200,000 票になり、おそらくこのデータベースは機能しなくなります。というわけで、このパズルを解く方法を考えています。
そして今、私はこれらの質問に行き着きました:
- データベースの設計を間違えたのでしょうか? つまり、もっと良くなるでしょうか?
- クエリを間違えましたか?
- 他に改善できることはありますか?
最初に行ったのはキャッシングです。しかし、OK、これで問題は劇的に解決します。しかし、私は SQL 関連のソリューションに興味があります (常に完璧に傾倒しています)。
2 番目に思いついたのは、これらの計算値をMeta
テーブルに入れ、投票手順中に変更することでした。しかし、私はそれを試すだけでは時間がありません。ちなみに、それだけの価値はありますか?または、エンタープライズ クラスのアプリはこれらの問題をどのように解決しますか?
ありがとう。
編集
インデックスを含めるのを忘れたなんて信じられません。どうぞ:
mysql> SHOW INDEXES IN Vote;
+-------+------------+-------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+-------+------------+-------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Vote | 0 | UNIQUE_UserId_TrackHash | 1 | UserId | A | 890 | NULL | NULL | | BTREE | |
| Vote | 0 | UNIQUE_UserId_TrackHash | 2 | TrackHash | A | 4450 | NULL | NULL | | BTREE | |
| Vote | 1 | INDEX_TrackHash | 1 | TrackHash | A | 4450 | NULL | NULL | | BTREE | |
| Vote | 1 | INDEX_CreatedAt | 1 | CreatedAt | A | 1483 | NULL | NULL | | BTREE | |
| Vote | 1 | UserId | 1 | UserId | A | 1483 | NULL | NULL | | BTREE | |
+-------+------------+-------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
mysql> SHOW INDEXES IN Track;
+-------+------------+----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+-------+------------+----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Track | 0 | PRIMARY | 1 | Hash | A | 2678 | NULL | NULL | | BTREE | |
| Track | 1 | INDEX_Likes | 1 | Likes | A | 66 | NULL | NULL | | BTREE | |
| Track | 1 | INDEX_Dislikes | 1 | Dislikes | A | 27 | NULL | NULL | | BTREE | |
+-------+------------+----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+