MySQL 문서에 따르면 가장 왼쪽 필드가 조건의 일부인 경우 복합 인덱스가 계속 사용됩니다. 그러나이 테이블은 기본 키와 올바르게 결합하지 않습니다. 그 다음에 사용되는 왼쪽 두 필드의 다른 색인을 추가해야했습니다.복합 인덱스가 MySQL에서 사용되지 않음
테이블 중 하나는 메모리이며 기본적으로 메모리는 그룹/주문에 사용할 수없는 해시 인덱스를 사용한다는 것을 알고 있습니다. 그러나 나는 메모리 테이블의 모든 행과 색인을 사용하지 않으므로 문제와 관련이 있다고 생각하지 않습니다.
무엇이 누락 되었습니까?
mysql> show create table pr_temp;
| pr_temp | CREATE TEMPORARY TABLE `pr_temp` (
`player_id` int(10) unsigned NOT NULL,
`insert_date` date NOT NULL,
[...]
PRIMARY KEY (`player_id`,`insert_date`) USING BTREE,
KEY `insert_date` (`insert_date`)
) ENGINE=MEMORY DEFAULT CHARSET=utf8 |
mysql> show create table player_game_record;
| player_tank_record | CREATE TABLE `player_game_record` (
`player_id` int(10) unsigned NOT NULL,
`game_id` smallint(5) unsigned NOT NULL,
`insert_date` date NOT NULL,
[...]
PRIMARY KEY (`player_id`,`insert_date`,`game_id`),
KEY `insert_date` (`insert_date`),
KEY `player_date` (`player_id`,`insert_date`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 DATA DIRECTORY='...' INDEX DIRECTORY='...' |
mysql> explain select pgr.* from player_game_record pgr inner join pr_temp on pgr.player_id = pr_temp.player_id and pgr.insert_date = pr_temp.date_prev;
+----+-------------+---------+------+---------------------------------+-------------+---------+-------------------------------------------------------------------------+--------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+------+---------------------------------+-------------+---------+-------------------------------------------------------------------------+--------+-------+
| 1 | SIMPLE | pr_temp | ALL | PRIMARY | NULL | NULL | NULL | 174683 | |
| 1 | SIMPLE | pgr | ref | PRIMARY,insert_date,player_date | player_date | 7 | test_gamedb.pr_temp.player_id,test_gamedb.pr_temp.date_prev | 21 | |
+----+-------------+---------+------+---------------------------------+-------------+---------+-------------------------------------------------------------------------+--------+-------+
2 rows in set (0.00 sec)
mysql> explain select pgr.* from player_game_record pgr force index (primary) inner join pr_temp on pgr.player_id = pr_temp.player_id and pgr.insert_date = pr_temp.date_prev;
+----+-------------+---------+------+---------------+---------+---------+-------------------------------------------------------------------------+---------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+------+---------------+---------+---------+-------------------------------------------------------------------------+---------+-------+
| 1 | SIMPLE | pr_temp | ALL | PRIMARY | NULL | NULL | NULL | 174683 | |
| 1 | SIMPLE | pgr | ref | PRIMARY | PRIMARY | 7 | test_gamedb.pr_temp.player_id,test_gamedb.pr_temp.date_prev | 2873031 | |
+----+-------------+---------+------+---------------+---------+---------+-------------------------------------------------------------------------+---------+-------+
2 rows in set (0.00 sec)
두 개의 왼쪽 열 (player_id, insert_date)이 사용되는 기본 키가 작동해야한다고 생각합니다. 그러나 기본적으로 player_date 인덱스를 사용합니다. 기본 인덱스를 사용하도록 강제하는 경우 두 인덱스가 아닌 한 필드 만 사용하는 것처럼 보입니다.
갱신 2 : MySQL의 버전 5.5.27 - 로그 갱신 3 : 는
mysql> show indexes in player_game_record;
+--------------------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+--------------------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| player_game_record | 0 | PRIMARY | 1 | player_id | A | NULL | NULL | NULL | | BTREE | | |
| player_game_record | 0 | PRIMARY | 2 | insert_date | A | NULL | NULL | NULL | | BTREE | | |
| player_game_record | 0 | PRIMARY | 3 | game_id | A | 576276246 | NULL | NULL | | BTREE | | |
| player_game_record | 1 | insert_date | 1 | insert_date | A | 33304 | NULL | NULL | | BTREE | | |
+--------------------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
4 rows in set (1.08 sec)
mysql> select count(*) from player_game_record;
+-----------+
| count(*) |
+-----------+
| 576276246 |
+-----------+
1 row in set (0.00 sec)
무엇을 의미 "기본 키에 제대로 참여하지 않을 것이다"는 무엇입니까? 결과가 잘못되었거나'EXPLAIN SELECT'가'pgr'에서 기본 키를 사용하지 않는다는 것을 의미합니까?기본 키만 사용할 수있을 때 의심스러운 잘못된 동작을 설명하기 위해 새 인덱스를 제거하고 또 다른'EXPLAIN SELECT '를 게시 할 수 있습니까? –
나는 그것이 작동해야하는 인덱스를 사용하도록 강요한다면 분명히 explain (player_date 인덱스와 비교하여 볼 수있는 pgr 테이블의 행이 너무 많음)을 기반으로하지 않는다는 것을 의미합니다. 인덱스를 사용하지 않으며 쿼리가 너무 오래 걸립니다. player_date 인덱스를 제거하면 대신 insert_date가 선택되며, 인덱스를 생성하는 데 12 시간 이상이 소요되므로 제거하지 않을 것입니다. – Josh