私は2つのテーブルを持っています:
packages と package_to_tag の両方が MyISAM を実行しています
テーブルは次のように構成されています。
パッケージ
+----------------+------------------+----------------+
| aid(primary) | source | date(index) |
+----------------+------------------+----------------+
| 1 | CA | 2013-04-05 |
+----------------+------------------+----------------+
| 2 | FL | 2013-05-05 |
+----------------+------------------+----------------+
| 3 | UT | 2012-06-13 |
+----------------+------------------+----------------+
| 4 | VT | 2011-04-29 |
+----------------+------------------+----------------+
| 5 | CT | 2013-04-10 |
+----------------+------------------+----------------+
package_to_tag package-tag の一意のインデックスであり、package_aid とタグの両方にインデックスがあります
+---------------+------------------+
| package_aid | tag |
+---------------+------------------+
| 2 | sports |
+---------------+------------------+
| 2 | nba |
+---------------+------------------+
| 1 | food |
+---------------+------------------+
| 1 | burrito |
+---------------+------------------+
| 4 | hockey |
+---------------+------------------+
| 4 | sports |
+---------------+------------------+
| 3 | news |
+---------------+------------------+
| 5 | sports |
+---------------+------------------+
| 5 | nba |
+---------------+------------------+
タグとしてスポーツとnbaの両方を持っているパッケージを見つけるための私の基本的なクエリは次のとおりです。
SELECT package_aid FROM package_to_tag
WHERE tag IN("sports","nba")
GROUP BY package_aid
HAVING COUNT(*) = 2
結果に日付の並べ替えを追加しようとするまで、これはうまく機能します。(私のパッケージ レコード セットは 400k の範囲のどこかにあることに注意してください)
一致するタグに基づいてソースを取得するための私のクエリは次のとおりです。
SELECT package_aid, source
FROM package_to_tag
RIGHT JOIN packages ON packages.aid = package_to_tag.package_aid
AND tag IN("sports","nba")
GROUP BY package_aid
HAVING COUNT(*) = 2
ORDER BY date DESC
LIMIT 500
これは、400k レコードの場合、最大 5 秒かかります。date
ソートを削除しない限り。その後、1 秒もかかりません。したがって、私は常に IN ステートメントでかなりの成功を収めていたので、最初の結果セットを次のように絞り込んでみました。
SELECT aid,source FROM packages
WHERE aid IN(
SELECT package_aid FROM package_to_tag
WHERE tag IN("sports","nba")
GROUP BY package_aid
HAVING COUNT(*) = 2
)
ORDER BY date DESC
LIMIT 500
レコード セット全体ではなく、約 8 ~ 10,000 レコードにのみ並べ替えを適用すると考えました。
しかし、これだけでデータベースの使用率が 100% に固定され、再起動を余儀なくされます.... 余分なタグを使用して内側の選択を合計 80 レコード以下に絞り込んだとしても。
このクエリだけを実行してみました:
SELECT package_aid FROM package_to_tag
WHERE tag IN("sports","nba")
GROUP BY package_aid
HAVING COUNT(*) = 2
これにより、1 秒以内に 8 ~ 10,000 のレコードが返されます。
私は何が欠けていますか?