私はAmazon RDSでMySQLデータベースを持つアプリケーションを使っています。質問内のテーブルは、次のような設定されている:MySQLテーブルインデックスの最適化
CREATE TABLE `log` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`timestamp` datetime NOT NULL,
`username` varchar(45) NOT NULL,
.. snip some varchar and int fields ..
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
このシステムは、しばらくの間、ベータ版になっていると、すでにデータセットは非常に巨大で、クエリがかなり遅くなるし始めています。
SELECT COUNT(*) FROM log --> 16307224 (takes 105 seconds to complete)
この表はかなりのみ意味、一般的に完了するために、周りの100-180秒を取って1000のと6000行の間に何かを与えるこの
SELECT timestamp, username, [a few more] FROM log
WHERE timestamp BETWEEN '2012-03-30 08:00:00' AND '2012-03-30 16:00:00'
AND username='XX'
のようなクエリオフつのレポートを構築するために使用されますWebアプリケーションはタイムアウトして空のレポートを残します(私もタイムアウトを調べますが、この問題は根本的な原因です)。
私はデータベースにはあまりよくありませんが、ここで私を殺しているのは私の推測です。私が考えているのは、おそらく何とかタイムスタンプをインデックスとして使用すべきだということです。タイムスタンプはユーザー名に沿って一意性を提供する必要があります(私はidフィールドを何も使用しません)。
私はすべての耳に最適化のための提案を誰もがある場合。
UPDATE:
表は今SELECT
文の次
CREATE TABLE `log` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`timestamp` datetime NOT NULL,
`username` varchar(45) NOT NULL,
.. snip ..
`task_id` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `index_un_ts` (`timestamp`,`username`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
EXPLAIN
に変更されるようになり、タイムスタンプ列とユーザーIDで、次の
id => 1
select_type => SIMPLE
table => log
type => range
possible_keys => index_un_ts
key => index_un_ts
key_len => 55
ref =>
rows => 52258
Extra => Using where; Using index
MyISAMに切り替えることができます。たとえば、毎日cronでデータを集計し、別のレポート表に保管します。 –