views
訪問者の IP、投稿 ID (これらのフィールドの主キーを取得しました)、およびタイムスタンプを含むエントリをテーブル ( ) に挿入することにより、誰がいつ、どの投稿を閲覧したかを追跡するブログを取得しました。
次に、このテーブルを使用して、過去の日/週/月/年および全期間の各カテゴリ (4 つを取得) の上位 5 件の投稿を表示します。つまり、合計 20 個のクエリが実行され、それぞれのクエリに 0.2 ~ 0.7 秒かかります... 私のページの読み込みには 7 秒強かかりますが、これはひどいことです。
ここに私のデータベース構造に関するいくつかの有用な情報があります:
+---------------------+ +----------------------+
| posts (82 rows) | | views (50k rows) |
+=====================+ +======================+
| id (primary) | | ip (primary) |
+---------------------+ +----------------------+
| type | | article_id (primary) |
+---------------------+ +----------------------+
| thumbnail | | date (index) |
+---------------------+ +----------------------+
| title (index) |
+---------------------+
| url |
+---------------------+
| description (index) |
+---------------------+
| content |
+---------------------+
| date |
+---------------------+
| lastmod |
+---------------------+
| sources |
+---------------------+
| tags |
+---------------------+
| published |
+---------------------+
| ... |
+---------------------+
は...
、投稿の英語版の追加フィールド ( url_en
、title_en
、description_en
、tags_en
およびcontent_en
) を表します。
これが私の巨大なクエリの1つです(基本的にはすべて同じです):
SELECT p.title, p.id, p.url, tmp.cnt AS views
FROM posts AS p
LEFT JOIN (SELECT COUNT(*) AS cnt, article_id -- 0.34s
FROM views
WHERE article_id IN (SELECT id
FROM posts
WHERE id <> 12 AND type = 'Tutoriel') AND
date BETWEEN 01-01-2013 AND NOW() -- the 01-01-2013 is normally a variable but for testing purposes I've replaced it with a fixed date here
GROUP BY article_id
ORDER BY cnt DESC LIMIT 5) AS tmp
ON p.id = tmp.article_id
WHERE p.id IN (SELECT article_id
FROM (SELECT COUNT(*) AS cnt, article_id -- 0.34s
FROM views
WHERE article_id IN (SELECT id
FROM posts
WHERE id <> 12 AND type = 'Tutoriel')
AND date BETWEEN 01-01-2013 AND NOW()
GROUP BY article_id
ORDER BY cnt DESC LIMIT 5) AS tmp2
)
ORDER BY views DESC
BETWEEN
すべての投稿の全期間の統計情報を取得したため (つまり、カテゴリや日付に依存しない)、実行に 0.03 秒しかかからないという正確なクエリを取得したため、ほとんどの時間を費やしているのはこの句であることがわかりました。
私はこのクエリをあらゆる方法で調べましたが、よりシンプルで最適化された方法でそれを記述する方法を見つけることができませんでした...それでも、方法が必要だと感じています。たぶん、ここで明らかな何かが欠けているだけです。
私を悩ませていることの 1 つは、サブクエリの重複です。投稿データと関連ビュー数の両方を取得する他の方法は見つかりませんでした。
私が考えているのは、ユーザーがその期間のタブをクリックしたときに、その期間ごとにAJAXリクエストを実行することです(タブビューです)。ただし、それで問題が実際に解決されるわけではなく、汚い回避策のように感じられます。
posts
次のいずれかの方法でテーブルを分割できます。
- フランス語版用の表と英語版用の表
- よくアクセスされるフィールド (
title
、description
、url
) 用の 1 つのテーブルと、残りのフィールド用の別のテーブル - 上記の組み合わせ
私が間違っていなければ、これは少しスピードアップする可能性があります。
これについて誰かアドバイスをいただけますか?ところで、ここまで付き合ってくれてありがとう:)