[英]Optimize MySQL View that uses self-join
我有此表需要执行自联接:
+----+------+-------+-----+------+-------+-----------+---------+------+
| id | type | panel | row | port | cable | cablePort | conType | B_id |
+----+------+-------+-----+------+-------+-----------+---------+------+
| 1 | 1 | A | 1 | 1 | | | 1 | |
| 2 | 1 | A | 1 | 2 | | | 1 | |
| 3 | 1 | A | 1 | 3 | | | 1 | |
| 4 | 1 | A | 1 | 4 | | | 1 | |
| 5 | 1 | A | 1 | 5 | | | 1 | |
| 6 | 1 | A | 1 | 6 | | | 1 | |
| 7 | 1 | A | 1 | 7 | | | 1 | |
| 8 | 1 | A | 1 | 8 | | | 1 | |
| 9 | 1 | A | 1 | 9 | | | 1 | |
| 10 | 1 | A | 1 | 10 | | | 1 | |
+----+------+-------+-----+------+-------+-----------+---------+------+
(需要为id和B_id执行自我加入)
想要此表的结果:
+------+--------+---------+-------+--------+---------+-------------+-----------+--------+--------+---------+-------+--------+---------+-------------+-----------+
| a_id | a_type | a_panel | a_row | a_port | a_cable | a_cablePort | a_conType | b_B_id | b_type | b_panel | b_row | b_port | b_cable | b_cablePort | b_conType |
+------+--------+---------+-------+--------+---------+-------------+-----------+--------+--------+---------+-------+--------+---------+-------------+-----------+
| 1 | 1 | A | 1 | 1 | NULL | NULL | 1 | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
| 2 | 1 | A | 1 | 2 | NULL | NULL | 1 | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
| 3 | 1 | A | 1 | 3 | NULL | NULL | 1 | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
| 4 | 1 | A | 1 | 4 | NULL | NULL | 1 | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
| 5 | 1 | A | 1 | 5 | NULL | NULL | 1 | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
| 6 | 1 | A | 1 | 6 | NULL | NULL | 1 | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
| 7 | 1 | A | 1 | 7 | NULL | NULL | 1 | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
| 8 | 1 | A | 1 | 8 | NULL | NULL | 1 | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
| 9 | 1 | A | 1 | 9 | NULL | NULL | 1 | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
| 10 | 1 | A | 1 | 10 | NULL | NULL | 1 | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
+------+--------+---------+-------+--------+---------+-------------+-----------+--------+--------+---------+-------+--------+---------+-------------+-----------+
(请注意,我在此记录中未指定任何B_id)
下面是我的表结构:
╔═══════════════╦═════════════╦══════╦═════╦═════════╦════════════════╗
║ Field ║ Type ║ Null ║ Key ║ Default ║ Extra ║
╠═══════════════╬═════════════╬══════╬═════╬═════════╬════════════════╣
║ id ║ int(11) ║ NO ║ PRI ║ NULL ║ auto_increment ║
║ type ║ varchar(45) ║ YES ║ ║ NULL ║ ║
║ panel ║ varchar(45) ║ YES ║ ║ NULL ║ ║
║ row ║ varchar(45) ║ YES ║ ║ NULL ║ ║
║ port ║ varchar(45) ║ YES ║ ║ NULL ║ ║
║ cable ║ varchar(45) ║ YES ║ ║ NULL ║ ║
║ cablePort ║ varchar(45) ║ YES ║ ║ NULL ║ ║
║ conType ║ varchar(45) ║ YES ║ MUL ║ NULL ║ ║
║ B_id ║ int ║ YES ║ MUL ║ NULL ║ ║
╚═══════════════╩═════════════╩══════╩═════╩═════════╩════════════════╝
最后是执行自连接的View。
select distinct
`a`.`id` AS `a_id`,
`a`.`type` AS `a_type`,
`a`.`panel` AS `a_panel`,
`a`.`row` AS `a_row`,
`a`.`port` AS `a_port`,
`a`.`cable` AS `a_cable`,
`a`.`cablePort` AS `a_cablePort`,
`a`.`conType` AS `a_conType`,
`a`.`B_id` AS `b_B_id`,
`b`.`type` AS `b_type`,
`b`.`panel` AS `b_panel`,
`b`.`row` AS `b_row`,
`b`.`port` AS `b_port`,
`b`.`cable` AS `b_cable`,
`b`.`cablePort` AS `b_cablePort`,
`b`.`conType` AS `b_conType`
from `mmr` `a`
left join `mmr` `b`
ON (`a`.`id` = `b`.`B_id`)
问题在于执行我的数据提取视图是不可接受的。 提取10000条记录大约需要1分钟或更长时间。
您能否就如何优化查询以及导致数据提取执行缓慢的原因向我提出建议。
额外:
我还创建了另一个视图,该视图将从上面的视图中提取数据。 该视图将进一步需要操纵数据并提供更详细的数据以供查看。
select
`a`.`a_id` AS `a_id`,
`a`.`a_type` AS `a_type`,
`a`.`a_panel` AS `a_panel`,
`a`.`a_row` AS `a_row`,
`a`.`a_port` AS `a_port`,
`a`.`a_cable` AS `a_cable`,
`a`.`a_cablePort` AS `a_cablePort`,
`a`.`a_conType` AS `a_conType`,
`a`.`a_conTypeDesc` AS `a_conTypeDesc`,
`a`.`b_B_id` AS `b_B_id`,
`a`.`b_type` AS `b_type`,
`a`.`b_panel` AS `b_panel`,
`a`.`b_row` AS `b_row`,
`a`.`b_port` AS `b_port`,
`a`.`b_cable` AS `b_cable`,
`a`.`b_cablePort` AS `b_cablePort`,
`a`.`b_conType` AS `b_conType`,
`a`.`b_conTypeDesc` AS `b_conTypeDesc`,
(case
when
((`a`.`b_panel` = `b`.`b_panel`)
and (`a`.`b_row` = `b`.`b_row`))
then
concat(`a`.`b_panel`,
_latin1'-',
`a`.`b_row`,
_latin1'(',
(case
when (cast(`a`.`b_port` as signed) > cast(`b`.`b_port` as signed)) then `b`.`b_port`
else `a`.`b_port`
end),
_latin1',',
(case
when (cast(`a`.`b_port` as signed) < cast(`b`.`b_port` as signed)) then `b`.`b_port`
else `a`.`b_port`
end),
_latin1')')
when
((`a`.`b_row` <> `b`.`b_row`)
and (`a`.`b_cablePort` <> _latin1''))
then
concat(`a`.`b_panel`,
_latin1'-',
`a`.`b_row`,
_latin1'(',
`a`.`b_port`,
_latin1'),',
`b`.`b_row`,
_latin1'(',
`b`.`b_port`,
_latin1')')
else concat(`a`.`b_panel`,
_latin1'-',
`a`.`b_row`,
_latin1'(',
`a`.`b_port`,
_latin1')')
end) AS `mmrport`
from
`vw_details` `a`
left join `vw_details` `b` ON (`a`.`b_cable` = `b`.`b_cable`)
and (`a`.`b_cablePort` = `b`.`b_cablePort`)
and (`a`.`b_B_id` <> `b`.`b_B_id`)
and (`a`.`b_type` = `b`.`b_type`)
and (`a`.`b_panel` = `b`.`b_panel`)
and (`a`.`b_conType` = `b`.`b_conType`)
(**上面的视图,数据提取持续时间非常不可接受)
查看结果如下:
+------+--------+---------+-------+--------+---------+-------------+-----------+----------------+--------+--------+---------+-------+--------+---------+-------------+-----------+----------------+------------+
| a_id | a_type | a_panel | a_row | a_port | a_cable | a_cablePort | a_conType | a_conTypeDesc | b_B_id | b_type | b_panel | b_row | b_port | b_cable | b_cablePort | b_conType | b_conTypeDesc | mmrport |
+------+--------+---------+-------+--------+---------+-------------+-----------+----------------+--------+--------+---------+-------+--------+---------+-------------+-----------+----------------+------------+
| 689 | 1 | A | 69 | 9 | 1 | 2 | 3 | Interconnected | 698 | 1 | A | 70 | 8 | 1 | 1 | 3 | Interconnected | A-70(7,8) |
| 690 | 1 | A | 69 | 10 | 1 | 2 | 3 | Interconnected | 697 | 1 | A | 70 | 7 | 1 | 1 | 3 | Interconnected | A-70(7,8) |
| 691 | 1 | A | 70 | 1 | 1 | 1 | 3 | Interconnected | 699 | 1 | A | 70 | 9 | 1 | 2 | 3 | Interconnected | A-70(9,10) |
| 692 | 1 | A | 70 | 2 | 1 | 1 | 3 | Interconnected | 700 | 1 | A | 70 | 10 | 1 | 2 | 3 | Interconnected | A-70(9,10) |
| 697 | 1 | A | 70 | 7 | 1 | 1 | 3 | Interconnected | 690 | 1 | A | 69 | 10 | 1 | 2 | 3 | Interconnected | A-69(9,10) |
| 697 | 1 | A | 70 | 7 | 1 | 1 | 3 | Interconnected | 690 | 1 | B | 30 | 8 | 1 | 2 | 4 | Disconnected | B-30(8,10) |
| 698 | 1 | A | 70 | 8 | 1 | 1 | 3 | Interconnected | 689 | 1 | A | 69 | 9 | 1 | 2 | 3 | Interconnected | A-69(9,10) |
| 698 | 1 | A | 70 | 8 | 1 | 1 | 3 | Interconnected | 689 | 1 | B | 30 | 10 | 1 | 2 | 4 | Disconnected | B-30(8,10) |
| 699 | 1 | A | 70 | 9 | 1 | 2 | 3 | Interconnected | 691 | 1 | A | 70 | 1 | 1 | 1 | 3 | Interconnected | A-70(1,2) |
| 699 | 1 | A | 70 | 9 | 1 | 2 | 3 | Interconnected | 691 | 1 | B | 30 | 9 | 1 | 1 | 4 | Disconnected | B-30(7,9) |
| 700 | 1 | A | 70 | 10 | 1 | 2 | 3 | Interconnected | 692 | 1 | A | 70 | 2 | 1 | 1 | 3 | Interconnected | A-70(1,2) |
| 700 | 1 | A | 70 | 10 | 1 | 2 | 3 | Interconnected | 692 | 1 | B | 30 | 7 | 1 | 1 | 4 | Disconnected | B-30(7,9) |
+------+--------+---------+-------+--------+---------+-------------+-----------+----------------+--------+--------+---------+-------+--------+---------+-------------+-----------+----------------+------------+
新增内容:问题:在MySQL上,此表上仅有15000条记录的简单自联接为什么要花很长时间才能处理?
如果您可以提出任何解决方法,我将不胜感激。
尝试将连接条件更改为第一步
select
`a`.`a_id` AS `a_id`,
`a`.`a_type` AS `a_type`,
`a`.`a_panel` AS `a_panel`,
`a`.`a_row` AS `a_row`,
`a`.`a_port` AS `a_port`,
`a`.`a_cable` AS `a_cable`,
`a`.`a_cablePort` AS `a_cablePort`,
`a`.`a_conType` AS `a_conType`,
`a`.`a_conTypeDesc` AS `a_conTypeDesc`,
`a`.`b_B_id` AS `b_B_id`,
`a`.`b_type` AS `b_type`,
`a`.`b_panel` AS `b_panel`,
`a`.`b_row` AS `b_row`,
`a`.`b_port` AS `b_port`,
`a`.`b_cable` AS `b_cable`,
`a`.`b_cablePort` AS `b_cablePort`,
`a`.`b_conType` AS `b_conType`,
`a`.`b_conTypeDesc` AS `b_conTypeDesc`,
(case
when
((`a`.`b_panel` = `b`.`b_panel`)
and (`a`.`b_row` = `b`.`b_row`))
then
concat(`a`.`b_panel`,
_latin1'-',
`a`.`b_row`,
_latin1'(',
(case
when (cast(`a`.`b_port` as signed) > cast(`b`.`b_port` as signed)) then `b`.`b_port`
else `a`.`b_port`
end),
_latin1',',
(case
when (cast(`a`.`b_port` as signed) < cast(`b`.`b_port` as signed)) then `b`.`b_port`
else `a`.`b_port`
end),
_latin1')')
when
((`a`.`b_row` <> `b`.`b_row`)
and (`a`.`b_cablePort` <> _latin1''))
then
concat(`a`.`b_panel`,
_latin1'-',
`a`.`b_row`,
_latin1'(',
`a`.`b_port`,
_latin1'),',
`b`.`b_row`,
_latin1'(',
`b`.`b_port`,
_latin1')')
else concat(`a`.`b_panel`,
_latin1'-',
`a`.`b_row`,
_latin1'(',
`a`.`b_port`,
_latin1')')
end) AS `mmrport`
from
`vw_details` `a`
left join `vw_details` `b` ON (`a`.`b_cable` = `b`.`b_cable`)
WHERE (`a`.`b_cablePort` = `b`.`b_cablePort`)
and (`a`.`b_B_id` <> `b`.`b_B_id`)
and (`a`.`b_type` = `b`.`b_type`)
and (`a`.`b_panel` = `b`.`b_panel`)
and (`a`.`b_conType` = `b`.`b_conType`)
如果不需要空记录,请使用INNER JOIN而不是LEFT JOIN。 另一个建议是,如果您使用的是php或asp.net之类的语言,请从查询中删除案例,然后使用服务器端语言进行此操作。 这将提高性能。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.