11

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
4

2 に答える 2

4

100%確信はありませんが、これは論理的に聞こえると思います。

テーブルをパーティション化しますBY RANGE (to_days(created_at))created_atフィールドはprimary_keyの一部です。選択クエリは、主キーの他の部分を使用しています。このように、サーバー最適化エンジンは、これが最も高速なインデックスであると判断します-パーティションとid-primary-partを使用します。

(選択につながる本当の原因を知らずに)partition-rangeをidに変更し、index1-keyの順序を変更することをお勧めします。

パーティショニングの詳細については、こちらをご覧ください

于 2013-01-28T12:34:38.177 に答える
1

エンジンが間違ったインデックスを選択する理由がわかりません。EQUALITY テストを持つインデックスは、>、<、または範囲を持つインデックスに取って代わると思います。ただし、正しいインデックスを強制するのに役立つ可能性のある別のオプションは、他の id 列に「計算された」値を強制することです。そのため、エンジンはインデックスに直接相関を行うことができない可能性があります...

WHERE field2_id = 12345 and id > 13314313

に変更

WHERE field2_id = 12345 and id + 0 > 13314313
于 2013-01-28T12:21:26.690 に答える