ビューを使用せずにクエリを実行するときのように、ビューを使用するときに mysql が同じインデックスを使用しないのはなぜですか。
ビューを作成する前の私のクエリ:
DESCRIBE SELECT membership_id, group_id, groups.name AS group_name, citizen_id, citizens.name, citizens.family, citizens.identification, memberships.birth, memberships.death, COALESCE(memberships.death, '2099-12-31 23:59:59') AS to_date
FROM memberships
LEFT JOIN groups ON (group_id = target_id)
LEFT JOIN citizens ON (citizen_id = member_id)
WHERE target_type = 31 AND member_type = 11
AND member_id = 5613956;
+----+-------------+-------------+--------+---------------+------------+---------+-------------------------------------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------------+--------+---------------+------------+---------+-------------------------------------+------+--------------------------+
| 1 | SIMPLE | memberships | ref | member,target | member | 10 | const,const | 6 | Using where; Using index |
| 1 | SIMPLE | groups | eq_ref | group_id | group_id | 8 | interfaceways.memberships.target_id | 1 | |
| 1 | SIMPLE | citizens | const | citizen_id | citizen_id | 8 | const | 1 | |
+----+-------------+-------------+--------+---------------+------------+---------+-------------------------------------+------+--------------------------+
それは機能し、高速です。メンバーシップをデバッグするたびに書くのは少し長いです。だから私はそのクエリに基づいてビューを作成しました:
CREATE VIEW group_members AS
SELECT membership_id, group_id, groups.name AS group_name, citizen_id, citizens.name, citizens.family, citizens.identification, memberships.birth, memberships.death, COALESCE(memberships.death, '2099-12-31 23:59:59') AS to_date
FROM memberships
LEFT JOIN groups ON (group_id = target_id)
LEFT JOIN citizens ON (citizen_id = member_id)
WHERE target_type = 31 AND member_type = 11;
しかし、5613956 のメンバーシップを取得しようとすると、次のようになります。
DESCRIBE SELECT * FROM group_members WHERE citizen_id = 5613956;
+----+-------------+-------------+--------+---------------+----------+---------+-------------------------------------+---------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------------+--------+---------------+----------+---------+-------------------------------------+---------+--------------------------+
| 1 | SIMPLE | memberships | ref | member,target | target | 1 | const | 5269 | Using where; Using index |
| 1 | SIMPLE | groups | eq_ref | group_id | group_id | 8 | interfaceways.memberships.target_id | 1 | |
| 1 | SIMPLE | citizens | ALL | NULL | NULL | NULL | NULL | 4766712 | Using where |
+----+-------------+-------------+--------+---------------+----------+---------+-------------------------------------+---------+--------------------------+
市民の「possible_keys」が NULL なのはなぜですか?
フィールドcitizen_idはSERIAL (= BIGINT(20) UNSIGNED UNIQUE NOT NULL AUTO_INCREMENT)
編集1
最初のクエリで member_id の代わりにcitizen_id を使用すると、次のようになります。
DESCRIBE SELECT membership_id, group_id, groups.name AS group_name, citizen_id, citizens.name, citizens.family, citizens.identification, memberships.birth, memberships.death, COALESCE(memberships.death, '2099-12-31 23:59:59') AS to_date
FROM memberships
LEFT JOIN groups ON (group_id = target_id)
LEFT JOIN citizens ON (citizen_id = member_id)
WHERE target_type = 31 AND member_type = 11
AND citizen_id = 5613956;
+----+-------------+-------------+--------+---------------+------------+---------+-------------------------------------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------------+--------+---------------+------------+---------+-------------------------------------+------+--------------------------+
| 1 | SIMPLE | citizens | const | citizen_id | citizen_id | 8 | const | 1 | |
| 1 | SIMPLE | memberships | ref | member,target | member | 10 | const,const | 6 | Using where; Using index |
| 1 | SIMPLE | groups | eq_ref | group_id | group_id | 8 | interfaceways.memberships.target_id | 1 | |
+----+-------------+-------------+--------+---------------+------------+---------+-------------------------------------+------+--------------------------+
編集2
ARIGHT JOIN
は問題を、挿入されたメンバー テーブルに移動します。(1054 x 必要な行、以前の 4 766 712 x 必要な行と比較して)
CREATE VIEW group_members AS
SELECT membership_id, group_id, groups.name AS group_name, citizen_id, citizens.name, citizens.family, citizens.identification, memberships.birth, memberships.death, COALESCE(memberships.death, '2099-12-31 23:59:59') AS to_date
FROM memberships
RIGHT JOIN groups ON (group_id = target_id)
RIGHT JOIN citizens ON (citizen_id = member_id)
WHERE target_type = 31 AND member_type = 11;
DESCRIBE SELECT * FROM group_members WHERE citizen_id = 5613956;
+----+-------------+-------------+--------+---------------+------------+---------+-------------------------------------+-------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------------+--------+---------------+------------+---------+-------------------------------------+-------+--------------------------+
| 1 | SIMPLE | citizens | const | citizen_id | citizen_id | 8 | const | 1 | |
| 1 | SIMPLE | memberships | index | NULL | member | 45 | NULL | 10540 | Using where; Using index |
| 1 | SIMPLE | groups | eq_ref | group_id | group_id | 8 | interfaceways.memberships.target_id | 1 | |
+----+-------------+-------------+--------+---------------+------------+---------+-------------------------------------+-------+--------------------------+
編集 3 興味深いメモ: ビュー自体が失敗するインデックスを使用するため、これはより高速です。
SELECT * FROM (SELECT * FROM group_members) AS t WHERE citizen_id = 5613956;
6 rows in set (0.03 sec)
DESCRIBE SELECT * FROM (SELECT * FROM group_members) AS t WHERE citizen_id = 5613956;
+----+-------------+-------------+--------+---------------+------------+---------+-------------------------------------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------------+--------+---------------+------------+---------+-------------------------------------+------+--------------------------+
| 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 4423 | Using where |
| 2 | DERIVED | memberships | ref | member,target | target | 1 | | 5270 | Using where; Using index |
| 2 | DERIVED | groups | eq_ref | group_id | group_id | 8 | interfaceways.memberships.target_id | 1 | |
| 2 | DERIVED | citizens | eq_ref | citizen_id | citizen_id | 8 | interfaceways.memberships.member_id | 1 | |
+----+-------------+-------------+--------+---------------+------------+---------+-------------------------------------+------+--------------------------+
編集 4 YaKs コメント
CREATE VIEW group_members AS
SELECT membership_id, group_id, groups.name AS group_name, citizen_id, citizens.name, citizens.family, citizens.identification, memberships.birth, memberships.death
FROM memberships
LEFT JOIN groups ON (group_id = target_id)
LEFT JOIN citizens ON (citizen_id = member_id)
WHERE target_type = 31 AND member_type = 11;
DESCRIBE SELECT * FROM group_members WHERE citizen_id = 5613956;
+----+-------------+-------------+--------+---------------+----------+---------+-------------------------------------+---------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------------+--------+---------------+----------+---------+-------------------------------------+---------+--------------------------+
| 1 | SIMPLE | memberships | ref | member,target | target | 1 | const | 5270 | Using where; Using index |
| 1 | SIMPLE | groups | eq_ref | group_id | group_id | 8 | interfaceways.memberships.target_id | 1 | |
| 1 | SIMPLE | citizens | ALL | NULL | NULL | NULL | NULL | 4766736 | Using where |
+----+-------------+-------------+--------+---------------+----------+---------+-------------------------------------+---------+--------------------------+
編集 5 jcho360 コメント
ANALYZE TABLE group_members;
+-----------------------------+---------+----------+-------------------------------------------------+
| Table | Op | Msg_type | Msg_text |
+-----------------------------+---------+----------+-------------------------------------------------+
| interfaceways.group_members | analyze | Error | 'interfaceways.group_members' is not BASE TABLE |
| interfaceways.group_members | analyze | error | Corrupt |
+-----------------------------+---------+----------+-------------------------------------------------+
2 rows in set (0.00 sec)
ANALYZE TABLE memberships;
+---------------------------+---------+----------+----------+
| Table | Op | Msg_type | Msg_text |
+---------------------------+---------+----------+----------+
| interfaceways.memberships | analyze | status | OK |
+---------------------------+---------+----------+----------+
1 row in set (0.02 sec)
ANALYZE TABLE citizens;
+------------------------+---------+----------+----------+
| Table | Op | Msg_type | Msg_text |
+------------------------+---------+----------+----------+
| interfaceways.citizens | analyze | status | OK |
+------------------------+---------+----------+----------+
1 row in set (0.11 sec)
ANALYZE TABLE groups;
+----------------------+---------+----------+----------+
| Table | Op | Msg_type | Msg_text |
+----------------------+---------+----------+----------+
| interfaceways.groups | analyze | status | OK |
+----------------------+---------+----------+----------+
1 row in set (0.01 sec)