1

私はこのテーブルを持っています:

CREATE TABLE IF NOT EXISTS `test1_nopart` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `idAccount` int(10) unsigned NOT NULL,
  `data` mediumint(8) unsigned NOT NULL,
  `date` date NOT NULL,
  PRIMARY KEY (`id`),
  KEY `date` (`date`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

このテーブルに 10 000 000 行を入力します。日付による再分割は均一です

EXPLAIN SELECT * FROM `test1_nopart` WHERE date = "2014-03-04" 

これが結果です

id  select_type   table        type     possible_keys   key     key_len     ref     rows        Extra
1   SIMPLE     test1_nopart     ALL     NULL            NULL    NULL        NULL    7875981     Using where

=> 説明なしで 3.6 秒 (約) 3000 行の結果

ご覧のとおり、インデックスは使用されておらず、possible_keys 列の一部ではありません!

カバリング インデックス ウェイを使用した同じリクエスト

EXPLAIN SELECT date FROM `test1_nopart` WHERE date = "2014-03-04"

結果:

id  select_type     table      type     possible_keys   key     key_len     ref     rows        Extra
1   SIMPLE       test1_nopart   index   NULL            date       3        NULL    7875981     Using where; Using index

=> 説明なしで 3000 行の結果に対して 2.8 秒 (約)

MySQL がこのインデックス (DATE) を適切に使用しないのはなぜですか ???

情報: - VM サーバー (私たちの開発環境、ハードウェア構成はわかりません) - MySQL 5.5.8

SHOW INDEX FROM test1_nopart

結果:

Table   Non_unique  Key_name    Seq_in_index    Column_name     Collation   Cardinality     Sub_part    Packed  Null    Index_type  Comment     Index_comment
test1_nopart    0   PRIMARY     1   id  A   7875981     NULL    NULL        BTREE        
test1_nopart    1   date    1   date    A   6077    NULL    NULL        BTREE        
  • 日付 2014-03-04 => 3134 行
  • 合計 (ロールアップ) => 7 875 488
  • テーブルには 2556 個の異なる「日付」値があります
4

4 に答える 4

1

MySQL クエリ オプティマイザーは、日付インデックスのインデックス トラバーサルにクラスター化インデックス (内部ではgen_clust_indexとして知られている) へのダイブが含まれていることを確認します。これに照らして、MySQL Query Optimizer は、最初のクエリで完全なテーブル スキャンを実行し、2 番目のクエリで完全なインデックス スキャンを実行する方が簡単であると判断しました。

また、インデックスのカーディナリティと、それぞれの個別の値の行数を確認する必要がある場合もあります。

以下を実行します。

SELECT COUNT(1) datecount,`date` FROM test1_nopart GROUP BY `date` WITH ROLLUP;

あなたのコメントによると、6077 の異なる行が得られます。また、約10,000,000行あると言いました。代わりに次のクエリを実行します。

SELECT COUNT(1) datecount FROM test1_nopart WHERE `date` = '2014-03-14';

カウントと合計に注意してください。

10,000,000 の 5% は 500,000 です

日付が「2014-03-14」の行が 500,000 行を超える場合、MySQL はその特定の値に対して適切にインデックスを使用しません。

SHOW INDEXES FROM test1_nopart;テーブルが InnoDB なので信用できません。MyISAM は正確な数を表示します。InnoDB は、Dives into the Index に基づいて数値を生成します。

いずれかの日付の datecount が行の総数の 5% を超えると、MySQL クエリ オプティマイザーは処理を停止してフル スキャンを実行します。

アップデート

5% の経験則は窓の外です。別のカバリング インデックスを作成して、MySQL Query Optimizer を騙してみてください。

ALTER TABLE test1_nopart ADD INDEX date_id_ndx (`date`,id);

クエリをもう一度試してください。

于 2011-12-29T17:26:13.370 に答える
0

これが私の考えです。

MySQLで取得しようとする最初のケースでは、dataカーディナリティが非常に低いため、dateインデックスを使用しません。dateそして、オプティマイザは以下を使用します: - セカンダリ インデックス - 行にアクセスするためにクラスター化 - データを取得するテーブル。

2 番目のケースでは、MySQL はインデックスからも選択したデータを取得できるため、インデックスを使用してテーブルを通過dateするdate方が簡単です (つまり、MySQL はテーブル全体ではなくインデックスのみをスキャンして同じデータを取得できます)。以下を使用します。 - セカンダリ インデックス

于 2011-12-29T18:47:46.663 に答える
0

カーディナリティの問題ではありません。

私は多くのテストを行い、問題を説明する別の投稿を作成しました。

https://stackoverflow.com/questions/8679940/primary-key-index-with-a-datetime-as-first-part-of-the-compound-key-is-never-use

問題は、最初のキーが日時の場合にのみ発生しました...

于 2011-12-30T13:36:41.803 に答える
0

ひょっとして、この言葉と何か関係があるのか​​もしれませんdate

予約語ではなくフィールドを使用するというヒントを MySQL に与えるようにしてください。

SELECT date FROM `test1_nopart` WHERE `test1_nopart`.`date` = "2014-03-04"
于 2011-12-29T17:17:50.313 に答える