优化使用自联接的MySQL视图

时间:2014-05-27 06:40:37

标签: mysql views 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)  |
+------+--------+---------+-------+--------+---------+-------------+-----------+----------------+--------+--------+---------+-------+--------+---------+-------------+-----------+----------------+------------+

新: 问:为什么只需要在这个表上为15000条记录进行简单的自联接需要很长时间才能在MySQL中处理?

如果您可以为此建议任何解决方法,我将非常感谢。

1 个答案:

答案 0 :(得分:0)

尝试将连接条件更改为第一步中的位置

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这样的语言从你的查询中删除案例,并使用服务器端语言。这会提高性能。