MySQL : Union Subselects의 지수 사용
-
05-07-2019 - |
문제
~ 안에 MySQL 5.0.75-0ubuntu10.2
그런 고정 테이블 레이아웃이 있습니다.
테이블 parent
ID 테이블로 parent2
ID 테이블로 children1
부모와 함께
CREATE TABLE `Parent` (
`id` int(11) NOT NULL auto_increment,
`name` varchar(200) default NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB
CREATE TABLE `Parent2` (
`id` int(11) NOT NULL auto_increment,
`name` varchar(200) default NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB
CREATE TABLE `Children1` (
`id` int(11) NOT NULL auto_increment,
`parentId` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `parent` (`parentId`)
) ENGINE=InnoDB
아이들은 테이블 중 하나에 부모가 있습니다. Parent
또는 Parent2
. 아이들을 데려 가야 할 때 다음과 같은 쿼리를 사용합니다.
select * from Children1 c
inner join (
select id as parentId from Parent
union
select id as parentId from Parent2
) p on p.parentId = c.parentId
설명 이 쿼리는 다음과 같습니다.
+----+--------------+------------+-------+---------------+---------+---------+------+------+-----------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------+------------+-------+---------------+---------+---------+------+------+-----------------------------------------------------+
| 1 | PRIMARY | NULL | NULL | NULL | NULL | NULL | NULL | NULL | Impossible WHERE noticed after reading const tables |
| 2 | DERIVED | Parent | index | NULL | PRIMARY | 4 | NULL | 1 | Using index |
| 3 | UNION | Parent2 | index | NULL | PRIMARY | 4 | NULL | 1 | Using index |
| NULL | UNION RESULT | <union2,3> | ALL | NULL | NULL | NULL | NULL | NULL | |
+----+--------------+------------+-------+---------------+---------+---------+------+------+-----------------------------------------------------+
4 rows in set (0.00 sec)
레이아웃이 주어지면 합리적입니다.
이제 문제 : 이전 쿼리는 부모 요소에서 열을 반환하지 않기 때문에 다소 쓸모가 없습니다. 현재 내부 쿼리에 더 많은 열을 추가하면 더 이상 색인이 사용되지 않습니다.
mysql> explain select * from Children1 c inner join ( select id as parentId,name from Parent union select id as parentId,name from Parent2 ) p on p.parentId = c.parentId;
+----+--------------+------------+------+---------------+------+---------+------+------+-----------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------+------------+------+---------------+------+---------+------+------+-----------------------------------------------------+
| 1 | PRIMARY | NULL | NULL | NULL | NULL | NULL | NULL | NULL | Impossible WHERE noticed after reading const tables |
| 2 | DERIVED | Parent | ALL | NULL | NULL | NULL | NULL | 1 | |
| 3 | UNION | Parent2 | ALL | NULL | NULL | NULL | NULL | 1 | |
| NULL | UNION RESULT | <union2,3> | ALL | NULL | NULL | NULL | NULL | NULL | |
+----+--------------+------------+------+---------------+------+---------+------+------+-----------------------------------------------------+
4 rows in set (0.00 sec)
누구든지 (1 차) 지수가 더 이상 사용되지 않는 이유를 설명 할 수 있습니까? DB 레이아웃을 변경하지 않고 가능하면이 문제에 대한 해결 방법이 있습니까?
감사!
해결책
나는 Union에서 데이터 유형을 변환해야 할 가능성 때문에 파생 쿼리에서 여러 열을 꺼내기 시작하면 최적화가 떨어지는 것으로 생각합니다 (이 경우가 아니라 일반적으로). 또한 귀하의 쿼리가 본질적으로 상관 관계가있는 파생 하위 쿼리가되기를 원하기 때문일 수 있습니다. dev.mysql.com):
From Clause의 하위 쿼리는 조인 조작 조항 내에서 사용되지 않는 한 하위 쿼리가 될 수 없습니다.
당신이하려는 일 (그러나 유효하지는 않지만)은 다음과 같습니다.
select * from Children1 c
inner join (
select id as parentId from Parent where Parent.id = c.parentId
union
select id as parentId from Parent2 where Parent.id = c.parentId
) p
Result: "Unknown column 'c.parentId' in 'where clause'.
두 개의 왼쪽 조인과 ifnulls를 선호하지 않는 이유가 있습니까?
select *, IFNULL(p1.name, p2.name) AS name from Children1 c
left join Parent p1 ON p1.id = c.parentId
left join Parent2 p2 ON p2.id = c.parentId
쿼리의 유일한 차이점은 각 테이블에 부모가 있으면 두 행을 얻을 수 있다는 것입니다. 그것이 당신이 원하는/필요한 것이라면, 이것은 또한 잘 작동하고 결합은 빠르며 항상 색인을 사용합니다.
(select * from Children1 c join Parent p1 ON p1.id = c.parentId)
union
(select * from Children1 c join Parent2 p2 ON p2.id = c.parentId)
다른 팁
첫 번째 생각은 테이블에 "상당한"레코드를 삽입하고 분석 테이블을 사용하여 통계를 업데이트하는 것입니다. 4 개의 레코드가있는 테이블은 항상 인덱스를 통해 전체 스캔을 사용하여 읽는 것이 더 빠릅니다! 또한 색인을 사용하여 색인의 사용을 강요하고 계획이 어떻게 변하는 지 살펴볼 수 있습니다.
또한이 문서를 읽고 어떤 비트가 관련이 있는지 확인할 것입니다.mysql :: 설명을 통해 쿼리 최적화
이 기사도 유용 할 수 있습니다MySQL이 올바른 색인을 사용하도록 설득하는 7 가지 방법