私の問題は次のとおりです。
2,300 万行(1 年間のデータ)を含むテーブル メールメッセージがあります。
このテーブルの重要なフィールドは次のとおりです
- id (bigint)
- msgtimeutc (bigint)
- 件名 (小さなテキスト)
- 本文)
- 表示されるその他のデータ
このテーブルには全文索引があります:
CREATE FULLTEXT INDEX mailmessage_fulltext ON mailmessage (body,subject)
本文と件名のテキストを検索し、次のように msgtimeutcで日時で絞り込むリクエストを行う必要があります。
SELECT M.some_data
FROM mailmessage M
WHERE M.MSGTIMEUTC >= 1343651965 AND M.MSGTIMEUTC <= 1344170365
AND ( MATCH (M.BODY,M.SUBJECT) AGAINST ('test'));
mySQL
- 同時に 2 つのインデックスを使用することはできません (msgtimeutc のインデックスと fulltextindex のインデックス)。したがって、クエリは msgtimeutc で完全なテーブル スキャンを実行して終了します。
- msgtimeutc は bigint であるため、フルテキスト インデックスに含めることはできず、その上または下で実行しています。
そのため、クエリに時間がかかりすぎます (および I/O) !
このような交差を行うことを考えました (サンプル コードはテストされていません) 。
SELECT M1.some_data FROM mailmessage M1
WHERE M1.MSGTIMEUTC >= 1343651965 AND M1.MSGTIMEUTC <= 1344170365
INTERSECT
SELECT M2.some_data FROM mailmessage M2
WHERE ( MATCH (M2.BODY,M2.SUBJECT) AGAINST ('test'));
説明してください(スクロールバーで申し訳ありません):
+----+-------------+-------+----------+---------------------------------+----------------------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+----------+---------------------------------+----------------------+---------+------+------+-------------+
| 1 | SIMPLE | M | fulltext | msgtimeutc,mailmessage_fulltext | mailmessage_fulltext | 0 | | 1 | Using where |
+----+-------------+-------+----------+---------------------------------+----------------------+---------+------+------+-------------+
しかし、それはmySQLには存在しません
以下の 2 つのような他のリクエストも、フル テーブル スキャンを実行しています。
SELECT M.some_data
FROM mailmessage M
WHERE
M.id in (
select m2.id from mailmessage m2 use index(mailmessage_fulltext)
where (MATCH (m2.BODY,m2.SUBJECT) AGAINST ('test'))
)
AND M.MSGTIMEUTC >= 1343651965 AND M.MSGTIMEUTC <= 1344170365;
また
SELECT M1.ATTACHMENTCOUNT AS ATCH_COUNT
FROM mailmessage AS M1
INNER JOIN mailmessage AS M2 ON M1.id = M2.id
WHERE (M1.MSGTIMEUTC >= 1343651965 AND M1.MSGTIMEUTC <= 1344170365)
AND (MATCH (M2.BODY,M2.SUBJECT) AGAINST ('test'))
両方のクエリ Explain Plan で、使用されているインデックスが 1 つだけ表示されます (フルテキスト)
だから私は日付でプログラム的に行をフィルタリングすることになるかもしれません...しかし、私は(ボリュームに関して)データベースソリューションを好むでしょう
何か案が ?