2016-05-19 7 views
0

テーブルには80万以上の行があります。私は時間間隔で行を抽出するクエリのパフォーマンスを改善する必要があります。MySQLはタイムスタンプカラムで自分のインデックスを無視します

私のテーブル:私はこのクエリを書くとき

EXPLAIN SELECT * FROM bets WHERE 
bets.stamp_end BETWEEN '2016-05-01 00:00:00' AND '2016-06-01 00:00:00'; 

+----+-------------+-------+-------+----------------------+----------------------+---------+------+--------+-------------+ 
| id | select_type | table | type | possible_keys  | key     | key_len | ref | rows | Extra  | 
+----+-------------+-------+-------+----------------------+----------------------+---------+------+--------+-------------+ 
| 1 | SIMPLE  | bets | **range** | bets_stamp_end_index | bets_stamp_end_index | 5  | NULL | **158210** | Using where | 
+----+-------------+-------+-------+----------------------+----------------------+---------+------+--------+-------------+ 

、インデックスが使用されることはありません:

EXPLAIN SELECT * FROM bets WHERE 
stamp_end >= DATE_SUB(DATE(NOW()), INTERVAL 56 DAY); 

+----+-------------+-------+------+----------------------+------+---------+------+--------+-----------------------------+ 
| id | select_type | table | type | possible_keys  | key | key_len | ref | rows | Extra      | 
+----+-------------+-------+------+----------------------+------+---------+------+--------+-----------------------------+ 
| 1 | SIMPLE  | bets | **ALL** | bets_stamp_end_index | NULL | NULL | NULL | **857651** | Using where; Using filesort | 
+----+-------------+-------+------+----------------------+------+---------+------+--------+-----------------------------+ 

注たまにインデックスは、このクエリで使用されて

CREATE TABLE `bets` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `user_id` int(11) NOT NULL, 
    ... 
    `stamp_end` timestamp NULL DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    KEY `bets_stamp_end_index` (`stamp_end`) 
) ENGINE=InnoDB AUTO_INCREMENT=875534 DEFAULT CHARSET=utf8; 

: 私はすでにOPTIMIZE TABLEを実行しています。最初のクエリでは、インデックスは一部の日付間隔でのみ使用されます。

なぜインデックスが使用されないのですか?どんな解決策ですか?インデックスを使用して

+0

stamp_end> = CURDATE() '試してみてください - INTERVAL 56 DAY' –

+0

ちょうど試してみました:完全なテーブルと同じ問題をインデックスを使用せずにスキャンしてください。 –

+0

'SELECT * FROM bets FORCE INDEX(bets_stamp_end_index)WHERE stamp_end> = CURDATE() - INTERVAL 56 DAY' –

答えて

0

インデックスB木とデータB木との間で前後に跳ねることを意味します。

テーブルの約20%未満をアクセスする必要がある場合は、バウンスする価値があります。

これ以上のアクセスが必要な場合は、実際にはテーブルをスキャンして、除外すると述べているものを除外した方が高速です。

(20%が不正確である、とオプティマイザが常に '正しい' のカットオフは行いません。)

-1

SAMPLE

MariaDB [bb]> CREATE TABLE `bets` (
    -> `id` int(11) NOT NULL AUTO_INCREMENT, 
    -> `user_id` int(11) NOT NULL, 
    -> 
    -> `stamp_end` timestamp NULL DEFAULT NULL, 
    -> PRIMARY KEY (`id`), 
    -> KEY `bets_stamp_end_index` (`stamp_end`) 
    ->) ENGINE=InnoDB AUTO_INCREMENT=875534 DEFAULT CHARSET=utf8; 
Query OK, 0 rows affected (0.13 sec) 

MariaDB [bb]> 
MariaDB [bb]> INSERT INTO bets (stamp_end) 
    -> SELECT DATE(now()) - INTERVAL seq HOUR FROM seq_1_to_300000; 
Query OK, 300000 rows affected, 1 warning (3.27 sec) 
Records: 300000 Duplicates: 0 Warnings: 1 

MariaDB [bb]> 
MariaDB [bb]> EXPLAIN SELECT * FROM bets WHERE 
    -> bets.stamp_end BETWEEN '2016-05-01 00:00:00' AND '2016-06-01 00:00:00'; 
+------+-------------+-------+-------+----------------------+----------------------+---------+------+------+-----------------------+ 
| id | select_type | table | type | possible_keys  | key     | key_len | ref | rows | Extra     | 
+------+-------------+-------+-------+----------------------+----------------------+---------+------+------+-----------------------+ 
| 1 | SIMPLE  | bets | range | bets_stamp_end_index | bets_stamp_end_index | 5  | NULL | 432 | Using index condition | 
+------+-------------+-------+-------+----------------------+----------------------+---------+------+------+-----------------------+ 
1 row in set (0.03 sec) 

MariaDB [bb]> 
MariaDB [bb]> EXPLAIN SELECT * FROM bets WHERE 
    -> stamp_end >= DATE_SUB(DATE(NOW()), INTERVAL 56 DAY); 
+------+-------------+-------+-------+----------------------+----------------------+---------+------+------+-----------------------+ 
| id | select_type | table | type | possible_keys  | key     | key_len | ref | rows | Extra     | 
+------+-------------+-------+-------+----------------------+----------------------+---------+------+------+-----------------------+ 
| 1 | SIMPLE  | bets | range | bets_stamp_end_index | bets_stamp_end_index | 5  | NULL | 1343 | Using index condition | 
+------+-------------+-------+-------+----------------------+----------------------+---------+------+------+-----------------------+ 
1 row in set (0.00 sec) 

MariaDB [bb]> 
+0

OPは 'function(field)'を使用しません。 OPは 'field <= function(static_value)'を使用します。 –

+0

@juergen - 私の間違いを申し訳ありません。私はすべてを読んでいない –

関連する問題