私は自分のシステムから送信されたすべてのメッセージを格納するInnoDBを使用しているテーブルを持っています。現在、この表には4,000万行があり、月に3百万回増加しています。大きなテーブルを持つMysql:このクエリを最適化する方法?
私の質問は基本的に、ユーザーから送信されたメッセージとデータ範囲内のメッセージを選択することです。ここでは単純なテーブルを作成しています:
CREATE TABLE `log` ( `id` int(10) NOT NULL DEFAULT '0', `type` varchar(10) NOT NULL DEFAULT '', `timeLogged` int(11) NOT NULL DEFAULT '0', `orig` varchar(128) NOT NULL DEFAULT '', `rcpt` varchar(128) NOT NULL DEFAULT '', `user` int(10) DEFAULT NULL, PRIMARY KEY (`id`), KEY `timeLogged` (`timeLogged`), KEY `user` (`user`), KEY `user_timeLogged` (`user`,`timeLogged`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
注:他のクエリのために個別のインデックスもあります。
クエリは次のようになります。
SELECT COUNT(*) FROM log WHERE timeLogged BETWEEN 1282878000 AND 1382878000 AND user = 20
問題は、このクエリは、ページがロードされるのを待つためにあまりにも多くの時間をあるユーザとサーバの負荷に依存し、10分に2分かかることです。私はmysqlキャッシュを有効にしてアプリケーションでキャッシュしていますが、問題は新しい範囲をユーザーが検索したときにキャッシュにヒットしないということです。
私の質問は以下のとおりです。
- はuser_timeLoggedインデックスは任意の違いを作る変えますか?
- これはMySQLと大きなデータベースに問題がありますか?つまり、Oracleや他のDBもこの問題を抱えていますか?
AFAIKでは、私のインデックスは正しく作成されており、このクエリはあまり時間がかかりません。
お手数をおかけしていただきありがとうございます。
ポストtimeLoggedログからEXPLAIN '次のSELECT COUNT(*)との間から出力(全てのクエリは冷たいバッファを実行します) 1282878000とAND 1382878000 AND user = 20; –
これをコメントとして投稿します。クエリ最適化には対応していませんが、すべてのメッセージを1つのテーブルに保存するのではなく、アーカイブ戦略を検討しましたか?月間750kの40mレコードは、4年分のデータを意味します。任意の年齢のメッセージが同じ頻度で照会されることが本当にある場合を除き、古いメッセージを別のテーブルに移動し、古いメッセージの要求をそのテーブルに送るロジックを実装することを検討するとよいでしょう。 –
クエリで最適化することはあまりありません。 * key_buffer *のサイズはどれくらいですか? – AndreKR