10

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

+-------------------+----------------+------+-----+---------------------+-----------------------------+
| Field             | Type           | Null | Key | Default             | Extra                       |
+-------------------+----------------+------+-----+---------------------+-----------------------------+
| id                | bigint(20)     | NO   | PRI | NULL                | auto_increment              |
| runtime_id        | bigint(20)     | NO   | MUL | NULL                |                             |
| place_id          | bigint(20)     | NO   | MUL | NULL                |                             |
| amended_timestamp | varchar(50)    | YES  |     | NULL                |                             |
| applicable_at     | timestamp      | NO   |     | CURRENT_TIMESTAMP   | on update CURRENT_TIMESTAMP |
| schedule_time     | timestamp      | NO   | MUL | 0000-00-00 00:00:00 |                             |
| quality_indicator | varchar(10)    | NO   |     | NULL                |                             |
| flow_rate         | decimal(15,10) | NO   |     | NULL                |                             |
+-------------------+----------------+------+-----+---------------------+-----------------------------+

私はschedule_timeにインデックスを持っています

create index table_index on table(schedule_time asc);

現在、テーブルには 2121552 件以上のレコードがあります。

私が理解できないのは、私が説明するときです

explain select runtime_id from table where schedule_time >= now() - INTERVAL 1 DAY;
+----+-------------+----------+-------+------------------------------+------------------------------+---------+------+-------+-------------+
| id | select_type | table    | type  | possible_keys                | key                          | key_len | ref  | rows  | Extra       |
+----+-------------+----------+-------+------------------------------+------------------------------+---------+------+-------+-------------+
|  1 | SIMPLE      | table    | range | table_index                  | table_index                  | 4       | NULL | 38088 | Using where |
+----+-------------+----------+-------+------------------------------+------------------------------+---------+------+-------+-------------+
1 row in set (0.00 sec)

上記のインデックスは使用されていますが、下のインデックスは使用されていません。

mysql> explain select runtime_id from table where schedule_time >= now() - INTERVAL 30 DAY;
+----+-------------+----------+------+------------------------------+------+---------+------+---------+-------------+
| id | select_type | table    | type | possible_keys                | key  | key_len | ref  | rows    | Extra       |
+----+-------------+----------+------+------------------------------+------+---------+------+---------+-------------+
|  1 | SIMPLE      | table    | ALL  | table_index                  | NULL | NULL    | NULL | 2118107 | Using where |
+----+-------------+----------+------+------------------------------+------+---------+------+---------+-------------+
1 row in set (0.00 sec)

データは 12 分ごとに更新され、クエリによって時間が経過すると 30 日または 60 日になると、非常に遅くなる可能性があるため、誰かがここで何が問題なのかを指摘していただければ幸いです。

私がそれを使用する予定の最後のクエリは次のとおりです

select avg(flow_rate),c.group from table a ,(select runtime_id from table where schedule_time >= now() - INTERVAL 1 DAY group by schedule_time ) b,place c  where a.runtime_id = b.runtime_id and a.place_id = c.id group by c.group;

更新 =====>

間のコメントによると、あまりにも失敗します。

mysql> explain select runtime_id from table where schedule_time between '2013-07-17 12:48:00' and '2013-08-17 12:48:00';
+----+-------------+----------+------+------------------------------+------+---------+------+---------+-------------+
| id | select_type | table    | type | possible_keys                | key  | key_len | ref  | rows    | Extra       |
+----+-------------+----------+------+------------------------------+------+---------+------+---------+-------------+
|  1 | SIMPLE      | table    | ALL  | table_index                  | NULL | NULL    | NULL | 2118431 | Using where |
+----+-------------+----------+------+------------------------------+------+---------+------+---------+-------------+
1 row in set (0.00 sec)

mysql> explain select runtime_id from table where schedule_time between '2013-08-16 12:48:00' and '2013-08-17 12:48:00';
+----+-------------+----------+-------+------------------------------+------------------------------+---------+------+-------+-------------+
| id | select_type | table    | type  | possible_keys                | key                          | key_len | ref  | rows  | Extra       |
+----+-------------+----------+-------+------------------------------+------------------------------+---------+------+-------+-------------+
|  1 | SIMPLE      | table    | range | table_index                  | table_index                  | 4       | NULL | 38770 | Using where |
+----+-------------+----------+-------+------------------------------+------------------------------+---------+------+-------+-------------+
1 row in set (0.00 sec)

更新 2 =======>

mysql> select count(*) from table where schedule_time between '2013-08-16 12:48:00' and '2013-08-17 12:48:00';
+----------+
| count(*) |
+----------+
|    19440 |
+----------+
1 row in set (0.01 sec)

mysql> select count(*) from table where schedule_time between '2013-07-17 12:48:00' and '2013-08-17 12:48:00';
+----------+
| count(*) |
+----------+
|   597132 |
+----------+
1 row in set (0.00 sec)

サーバーのバージョン: 5.5.24-0ubuntu0.12.04.1 (Ubuntu)

4

1 に答える 1

5

MySQL オプティマイザは、最速の処理を試みます。インデックスを使用すると、テーブル スキャンを実行するのと同じかそれ以上の時間がかかると判断された場合、使用可能なインデックスは破棄されます。

これは、例で実行していることです。

  • 範囲が小さい場合 (1 日)、インデックスは高速になります。
  • 範囲が大きい場合、テーブルを直接スキャンする方がはるかに多くのテーブルにヒットすることになります (インデックスを使用するには、インデックスを検索し、テーブルからインデックス付きレコードを取得する必要があることに注意してください。シーク)。

オプティマイザーよりもよく知っていると思われる場合 (完全ではありません)、INDEX ヒントを使用してください。

USE INDEX (index_list) ヒントは、名前付きインデックスの 1 つだけを使用してテーブル内の行を検索するように MySQL に指示します。代替構文 IGNORE INDEX (index_list) は、MySQL に特定のインデックスを使用しないように指示します。これらのヒントは、可能性のあるインデックスのリストから MySQL が間違ったインデックスを使用していることを EXPLAIN が示している場合に役立ちます。

于 2014-03-28T17:23:35.233 に答える