MySQL に、次のようなパーティション分割されたテーブルがあります。
CREATE TABLE `table1` (
`id` bigint(19) NOT NULL AUTO_INCREMENT,
`field1` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
`field2_id` int(11) NOT NULL,
`created_at` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY (`id`,`created_at`),
KEY `index1` (`field2_id`,`id`)
) ENGINE=InnoDB AUTO_INCREMENT=603221206 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
/*!50100 PARTITION BY RANGE (to_days(created_at))
(PARTITION p_0 VALUES LESS THAN (730485) ENGINE = InnoDB,
..... lots more partitions .....
PARTITION p_20130117 VALUES LESS THAN (735250) ENGINE = InnoDB) */;
これは、テーブルに対する典型的な SELECT クエリです。
SELECT field1 from TABLE1 where field2_id = 12345 and id > 13314313;
これについて説明すると、MySQL は index1 の代わりに PRIMARY を使用することを決定することがあります。最初の説明を行うとき、これはかなり一貫しているようです。しかし、何度か説明を繰り返した後、MySQL は最終的にインデックスを使用することにしました。問題は、このテーブルには何百万もの行があり、挿入と選択が毎秒数回のオーダーでヒットしていることです。間違ったインデックスを選択すると、これらの SELECT クエリに 1 秒未満ではなく、最大 40 秒かかっていました。ダウンタイムを実際にスケジュールできないため、テーブルで最適化を実行できません (サイズが大きいため、おそらく時間がかかります)。とにかく、この場合に役立つかどうかはわかりません。
インデックスを強制することでこれを修正したので、次のようになります。
SELECT field1 from TABLE1 FORCE INDEX (index1) WHERE field2_id = 12345 and id > 13314313;
これは MySQL 5.1.63 で実行していますが、現時点ではこれを取り除くことはできません。
私の質問は、MySQL が間違ったインデックスを選択するのはなぜですか? そして、すべてのクエリでインデックスを強制する以外に、それを修正するためにできることはありますか? パーティショニングは InnoDB エンジンを混乱させますか? 私は MySQL で多くの作業を行ってきましたが、この動作はこれまで見たことがありません。クエリは可能な限りシンプルで、インデックスも完全に一致しています。DB レイヤーが正しいことを行うと想定しているクエリがたくさんありますが、正しいインデックスを使用することを強制するすべてのクエリを実行したくありません。
更新 1:
これは、FORCE INDEX 句を使用しない典型的な Explain です。それが入れられると、可能なキー列には強制インデックスのみが表示されます。
id select_type table type possible_keys key key_len ref rows
1 SIMPLE table1 range PRIMARY,index1 index1 12 NULL 207