次のような MySQL テーブルがあります (意味のない列は削除されています)。
CREATE TABLE `my_data` (
`auto_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`created_ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_ts` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
`data_txt` varchar(256) CHARACTER SET utf8 NOT NULL,
`issued_ts` timestamp NULL DEFAULT NULL,
`account_id` int(11) NOT NULL,
PRIMARY KEY (`auto_id`),
KEY `account_issued_idx` (`account_id`,`issued_ts`),
KEY `account_issued_created_idx` (`account_id`,`issued_ts`,`created_ts`),
KEY `account_created_idx` (`account_id`,`created_ts`),
KEY `issued_idx` (`issued_ts`)
) ENGINE=InnoDB;
テーブルには約 9 億行あり、1 つの account_id がそれらの行の 65% 以上を占めています。account_idに依存するcreated_tsとissued_tsの両方の日付範囲にわたるクエリを作成するように求められています.account_idは、自動インクリメントキーに1:1の機能依存関係があるようです.
典型的なクエリは次のようになります。
SELECT *
FROM my_data
WHERE account_id = 1 AND
created_ts > TIMESTAMP('2012-01-01') AND
created_ts <= TIMESTAMP('2012-01-21')
ORDER BY created_ts DESC LIMIT 100;
クエリの EXPLAIN は、これを示しています。
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: my_data
type: range
possible_keys: account_issued_idx, account_issued_created_idx, account_created_idx,
key: account_issued_created_idx
key_len: 8
ref: NULL
rows: 365314721
Extra: Using where
問題は、クエリに時間がかかりすぎて、最終的に強制終了されることです。OS(Linux)がスワップスペースを使い果たしたため、データベースホストがダウンしました。
私はこの問題を繰り返し調査し、クエリを相関関係のないサブクエリに分割し、インデックスを強制し、明示的な SELECT 句を使用し、日付範囲のウィンドウを制限しようとしましたが、結果は同じです: パフォーマンスの低下 (あまりにも遅い)、ホストに負担がかかりすぎます(常に死にます)。
私の質問は次のとおりです。
データを日付範囲にスライスし、リアルタイム呼び出しで許容できるように実行するようにクエリを作成することは可能ですか? ( < 1 秒)
要求されているパフォーマンスを得るために、欠けている、または役立つ可能性のある最適化はありますか?
その他の提案、ヒント、または考えは大歓迎です。
ありがとう