3

ビューを使用せずにクエリを実行するときのように、ビューを使用するときに 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)
4

1 に答える 1

0

コメントを追加するつもりでしたが、多すぎます。

これを試して:

Select * from 
(SELECT member_id, 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) as table1
where member_id = 5613956;

必要に応じて、そのクエリの説明を作成できます。ビュー テーブルでも同じことが起こると思います。したがって、where member_id=5613956そのクエリを表示する where 条件で使用されていないため、市民 ID インデックスは使用されません。そのため、クエリはまったく同じではありません。

于 2012-07-05T13:27:23.133 に答える