Вложение select в предложении select займет вечность - PullRequest
0 голосов
/ 02 октября 2019
Table markclr
=============
  id     int(10) UNSIGNED AUTO_INCREMENT NOT NULL,
  name   varchar(255) NOT NULL,
  color  varchar(255) NOT NULL,
Table dvcgrp
=============
  id         int(10) UNSIGNED AUTO_INCREMENT NOT NULL,
  name       varchar(255) NOT NULL,
  markclrid  int(10) UNSIGNED NOT NULL,
Table dvc
=============
  id        int(10) UNSIGNED AUTO_INCREMENT NOT NULL,
  name      varchar(255) NOT NULL,
  shrtname  varchar(255) NOT NULL,
  dvceui    varchar(255) NOT NULL,
  dvcgrpid  int(10) UNSIGNED NOT NULL,
Table vhsrdt
=============
  id             int(10) UNSIGNED AUTO_INCREMENT NOT NULL,
  dvcid          int(10) UNSIGNED NOT NULL,
  dtrcvtm        timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  dtraw          varchar(255) NOT NULL,
  dtdvcnm        varchar(255) NOT NULL,
  dtgtwid        varchar(255) NOT NULL,
  dtport         int NOT NULL,
  dtdr           int NOT NULL,
  dtadr          varchar(255) NOT NULL,
  dtriptype      varchar(255),
  dlatitudedeg   decimal(10,8),
  dlongitudedeg  decimal(11,8),
  dvextgood      int(10) UNSIGNED NOT NULL,
  dgpscurrent    int(10) UNSIGNED NOT NULL,
  dignition      int(10) UNSIGNED NOT NULL,
  ddigin1        int(10) UNSIGNED NOT NULL,
  ddigin2        int(10) UNSIGNED NOT NULL,
  ddigout        int(10) UNSIGNED NOT NULL,
  dheadingdeg    varchar(255),
  dspeedkmph     varchar(255),
  dbatv          varchar(255),

Пожалуйста, помогите мне объяснить, что происходит с моим запросом ниже:

select
  dvc1.id,
  dvc1.name as dvcname,
  dvc1.dvceui as dvcdvceui,
  dvc1.shrtname as dvcshrtname,
  markclr.color as markclrcolor,
  (
    select
      tbl1.dtrcvtm
    from vhsrdt as tbl1
    where
      tbl1.dvcid = dvc1.id and
      tbl1.dtrcvtm = (
        select
          max(tbl2.dtrcvtm) as dtrcvtm
        from vhsrdt as tbl2
        where tbl2.dvcid = tbl1.dvcid
      )
  ) as dtrcvtm,
  (
    select
      tbl1.dtgtwid
    from vhsrdt as tbl1
    where
      tbl1.dvcid = dvc1.id and
      tbl1.dtrcvtm = (
        select
          max(tbl2.dtrcvtm) as dtrcvtm
        from vhsrdt as tbl2
        where tbl2.dvcid = tbl1.dvcid
      )
  ) as dtgtwid,
  (
    select
      tbl1.dtriptype
    from vhsrdt as tbl1
    where
      tbl1.dvcid = dvc1.id and
      tbl1.dtrcvtm = (
        select
          max(tbl2.dtrcvtm) as dtrcvtm
        from vhsrdt as tbl2
        where tbl2.dvcid = tbl1.dvcid
      )
  ) as dtriptype,
  (
    select
      tbl1.dlatitudedeg
    from vhsrdt as tbl1
    where
      tbl1.dvcid = dvc1.id and
      tbl1.dtrcvtm = (
        select
          max(tbl2.dtrcvtm) as dtrcvtm
        from vhsrdt as tbl2
        where tbl2.dvcid = tbl1.dvcid
      )
  ) as dlatitudedeg,
  (
    select
      tbl1.dlongitudedeg
    from vhsrdt as tbl1
    where
      tbl1.dvcid = dvc1.id and
      tbl1.dtrcvtm = (
        select
          max(tbl2.dtrcvtm) as dtrcvtm
        from vhsrdt as tbl2
        where tbl2.dvcid = tbl1.dvcid
      )
  ) as dlongitudedeg,
  (
    select
      tbl1.dspeedkmph
    from vhsrdt as tbl1
    where
      tbl1.dvcid = dvc1.id and
      tbl1.dtrcvtm = (
        select
          max(tbl2.dtrcvtm) as dtrcvtm
        from vhsrdt as tbl2
        where tbl2.dvcid = tbl1.dvcid
      )
  ) as dspeedkmph,
  (
    select
      tbl1.dheadingdeg
    from vhsrdt as tbl1
    where
      tbl1.dvcid = dvc1.id and
      tbl1.dtrcvtm = (
        select
          max(tbl2.dtrcvtm) as dtrcvtm
        from vhsrdt as tbl2
        where tbl2.dvcid = tbl1.dvcid
      )
  ) as dheadingdeg
from dvc as dvc1
left join dvcgrp on dvcgrp.id = dvc1.dvcgrpid
left join markclr on markclr.id = dvcgrp.markclrid

Таблица vhsrdt заполнена данными о 90K.
Если яИмитировать базу данных и выполнить этот запрос в моей среде разработки, используя XAMPP, он успешно извлечет менее чем за 1 сек.
Но если я выполнил этот запрос на производстве с использованием сервера Linux с MySQL 5.7, он никогда не завершится.

Я такжеЯ попытался удалить базу данных и построить всю структуру и данные снова, но он все еще не может завершить запрос.

Спасибо за вашу помощь.

Результат для EXPLAIN:

id | select_type        | table    | partitions | type   | possible_keys                                                                                                                                                                                                               | key                               | key_len | ref                     | rows | filtered | Extra
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1  | PRIMARY            | dvc1     |            | ALL    |                                                                                                                                                                                                                             |                                   |         |                         | 50   | 100      |
1  | PRIMARY            | dvcgrp   |            | eq_ref | PRIMARY                                                                                                                                                                                                                     | PRIMARY                           | 4       | klksensor.dvc1.dvcgrpid | 1    | 100      |
1  | PRIMARY            | markclr  |            | ALL    | PRIMARY                                                                                                                                                                                                                     |                                   |         |                         | 5    | 100      | Using where; Using join buffer (Block Nested Loop)
14 | DEPENDENT SUBQUERY | tbl1     |            | ref    | vhsrdt_dvcid_index,vhsrdt_dvcid_dtrcvtm_dtport_index,vhsrdt_dvcid_dtgtwid_index,vhsrdt_dvcid_dtriptype_index,vhsrdt_dvcid_dlatitudedeg_index,vhsrdt_dvcid_dlongitudedeg_index,vhsrdt_dvcid_dlatitudedeg_dlongitudedeg_index | vhsrdt_dvcid_dtrcvtm_dtport_index | 4       | klksensor.dvc1.id       | 1627 | 100      | Using where
15 | DEPENDENT SUBQUERY | tbl2     |            | ref    | vhsrdt_dvcid_index,vhsrdt_dvcid_dtrcvtm_dtport_index,vhsrdt_dvcid_dtgtwid_index,vhsrdt_dvcid_dtriptype_index,vhsrdt_dvcid_dlatitudedeg_index,vhsrdt_dvcid_dlongitudedeg_index,vhsrdt_dvcid_dlatitudedeg_dlongitudedeg_index | vhsrdt_dvcid_dtrcvtm_dtport_index | 4       | klksensor.tbl1.dvcid    | 1627 | 100      | Using index
12 | DEPENDENT SUBQUERY | tbl1     |            | ref    | vhsrdt_dvcid_index,vhsrdt_dvcid_dtrcvtm_dtport_index,vhsrdt_dvcid_dtgtwid_index,vhsrdt_dvcid_dtriptype_index,vhsrdt_dvcid_dlatitudedeg_index,vhsrdt_dvcid_dlongitudedeg_index,vhsrdt_dvcid_dlatitudedeg_dlongitudedeg_index | vhsrdt_dvcid_dtrcvtm_dtport_index | 4       | klksensor.dvc1.id       | 1627 | 100      | Using where
13 | DEPENDENT SUBQUERY | tbl2     |            | ref    | vhsrdt_dvcid_index,vhsrdt_dvcid_dtrcvtm_dtport_index,vhsrdt_dvcid_dtgtwid_index,vhsrdt_dvcid_dtriptype_index,vhsrdt_dvcid_dlatitudedeg_index,vhsrdt_dvcid_dlongitudedeg_index,vhsrdt_dvcid_dlatitudedeg_dlongitudedeg_index | vhsrdt_dvcid_dtrcvtm_dtport_index | 4       | klksensor.tbl1.dvcid    | 1627 | 100      | Using index
10 | DEPENDENT SUBQUERY | tbl1     |            | ref    | vhsrdt_dvcid_index,vhsrdt_dvcid_dtrcvtm_dtport_index,vhsrdt_dvcid_dtgtwid_index,vhsrdt_dvcid_dtriptype_index,vhsrdt_dvcid_dlatitudedeg_index,vhsrdt_dvcid_dlongitudedeg_index,vhsrdt_dvcid_dlatitudedeg_dlongitudedeg_index | vhsrdt_dvcid_dtrcvtm_dtport_index | 4       | klksensor.dvc1.id       | 1627 | 100      | Using where
11 | DEPENDENT SUBQUERY | tbl2     |            | ref    | vhsrdt_dvcid_index,vhsrdt_dvcid_dtrcvtm_dtport_index,vhsrdt_dvcid_dtgtwid_index,vhsrdt_dvcid_dtriptype_index,vhsrdt_dvcid_dlatitudedeg_index,vhsrdt_dvcid_dlongitudedeg_index,vhsrdt_dvcid_dlatitudedeg_dlongitudedeg_index | vhsrdt_dvcid_dtrcvtm_dtport_index | 4       | klksensor.tbl1.dvcid    | 1627 | 100      | Using index
8  | DEPENDENT SUBQUERY | tbl1     |            | ref    | vhsrdt_dvcid_index,vhsrdt_dvcid_dtrcvtm_dtport_index,vhsrdt_dvcid_dtgtwid_index,vhsrdt_dvcid_dtriptype_index,vhsrdt_dvcid_dlatitudedeg_index,vhsrdt_dvcid_dlongitudedeg_index,vhsrdt_dvcid_dlatitudedeg_dlongitudedeg_index | vhsrdt_dvcid_dtrcvtm_dtport_index | 4       | klksensor.dvc1.id       | 1627 | 100      | Using where
9  | DEPENDENT SUBQUERY | tbl2     |            | ref    | vhsrdt_dvcid_index,vhsrdt_dvcid_dtrcvtm_dtport_index,vhsrdt_dvcid_dtgtwid_index,vhsrdt_dvcid_dtriptype_index,vhsrdt_dvcid_dlatitudedeg_index,vhsrdt_dvcid_dlongitudedeg_index,vhsrdt_dvcid_dlatitudedeg_dlongitudedeg_index | vhsrdt_dvcid_dtrcvtm_dtport_index | 4       | klksensor.tbl1.dvcid    | 1627 | 100      | Using index
6  | DEPENDENT SUBQUERY | tbl1     |            | ref    | vhsrdt_dvcid_index,vhsrdt_dvcid_dtrcvtm_dtport_index,vhsrdt_dvcid_dtgtwid_index,vhsrdt_dvcid_dtriptype_index,vhsrdt_dvcid_dlatitudedeg_index,vhsrdt_dvcid_dlongitudedeg_index,vhsrdt_dvcid_dlatitudedeg_dlongitudedeg_index | vhsrdt_dvcid_dtrcvtm_dtport_index | 4       | klksensor.dvc1.id       | 1627 | 100      | Using where
7  | DEPENDENT SUBQUERY | tbl2     |            | ref    | vhsrdt_dvcid_index,vhsrdt_dvcid_dtrcvtm_dtport_index,vhsrdt_dvcid_dtgtwid_index,vhsrdt_dvcid_dtriptype_index,vhsrdt_dvcid_dlatitudedeg_index,vhsrdt_dvcid_dlongitudedeg_index,vhsrdt_dvcid_dlatitudedeg_dlongitudedeg_index | vhsrdt_dvcid_dtrcvtm_dtport_index | 4       | klksensor.tbl1.dvcid    | 1627 | 100      | Using index
4  | DEPENDENT SUBQUERY | tbl1     |            | ref    | vhsrdt_dvcid_index,vhsrdt_dvcid_dtrcvtm_dtport_index,vhsrdt_dvcid_dtgtwid_index,vhsrdt_dvcid_dtriptype_index,vhsrdt_dvcid_dlatitudedeg_index,vhsrdt_dvcid_dlongitudedeg_index,vhsrdt_dvcid_dlatitudedeg_dlongitudedeg_index | vhsrdt_dvcid_dtrcvtm_dtport_index | 4       | klksensor.dvc1.id       | 1627 | 100      | Using where
5  | DEPENDENT SUBQUERY | tbl2     |            | ref    | vhsrdt_dvcid_index,vhsrdt_dvcid_dtrcvtm_dtport_index,vhsrdt_dvcid_dtgtwid_index,vhsrdt_dvcid_dtriptype_index,vhsrdt_dvcid_dlatitudedeg_index,vhsrdt_dvcid_dlongitudedeg_index,vhsrdt_dvcid_dlatitudedeg_dlongitudedeg_index | vhsrdt_dvcid_dtrcvtm_dtport_index | 4       | klksensor.tbl1.dvcid    | 1627 | 100      | Using index
2  | DEPENDENT SUBQUERY | tbl1     |            | ref    | vhsrdt_dvcid_index,vhsrdt_dvcid_dtrcvtm_dtport_index,vhsrdt_dvcid_dtgtwid_index,vhsrdt_dvcid_dtriptype_index,vhsrdt_dvcid_dlatitudedeg_index,vhsrdt_dvcid_dlongitudedeg_index,vhsrdt_dvcid_dlatitudedeg_dlongitudedeg_index | vhsrdt_dvcid_dtrcvtm_dtport_index | 4       | klksensor.dvc1.id       | 1627 | 100      | Using where; Using index
3  | DEPENDENT SUBQUERY | tbl2     |            | ref    | vhsrdt_dvcid_index,vhsrdt_dvcid_dtrcvtm_dtport_index,vhsrdt_dvcid_dtgtwid_index,vhsrdt_dvcid_dtriptype_index,vhsrdt_dvcid_dlatitudedeg_index,vhsrdt_dvcid_dlongitudedeg_index,vhsrdt_dvcid_dlatitudedeg_dlongitudedeg_index | vhsrdt_dvcid_dtrcvtm_dtport_index | 4       | klksensor.tbl1.dvcid    | 1627 | 100      | Using index

1 Ответ

1 голос
/ 02 октября 2019

Из вашего оператора EXPLAIN видно, что запущено множество зависимых подзапросов ;хотя в вашем случае все они похожи, только с разницей в SELECT поле различия. К сожалению, MySQL не позволяет возвращать кортеж при использовании подзапроса в предложении SELECT.

Вы можете свести все эти подзапросы к одному подзапросу, вычислив все значения MAX() за один "запуск"", используя в предложении FROM. Вместо этого попробуйте следующий запрос:

select
  dvc1.id,
  dvc1.name as dvcname,
  dvc1.dvceui as dvcdvceui,
  dvc1.shrtname as dvcshrtname,
  markclr.color as markclrcolor,
  vhsrdt.dtrcvtm,
  vhsrdt.dtgtwid,
  vhsrdt.dtriptype,
  vhsrdt.dlatitudedeg,
  vhsrdt.dlongitudedeg,
  vhsrdt.dspeedkmph,
  vhsrdt.dheadingdeg
from dvc as dvc1
left join dvcgrp on dvcgrp.id = dvc1.dvcgrpid
left join markclr on markclr.id = dvcgrp.markclrid
left join vhsrdt on vhsrdt.dvcid = dvc1.id 
left join (select max(dtrcvtm) as max_dtrcvtm, dvcid
           from vhsrdt 
           group by dvcid
          ) as dt on dt.dvcid = vhsrdt.dvcid 
                     and dt.max_dtrcvtm = vhsrdt.dtrcvtm

Приведенный выше подход имеет ограничение вычисления значения max() для всех dvcid, независимо от того, нужно нам это или нет. Кроме того, это приведет к созданию временной таблицы (в оперативной памяти, если она мала, иначе на диске). К счастью, MySQL 8.0.14 представил LATERAL Производная таблица ;так что если вы можете обновить до последней версии MySQL, запрос performanceant будет выглядеть так:

select
  dvc1.id,
  dvc1.name as dvcname,
  dvc1.dvceui as dvcdvceui,
  dvc1.shrtname as dvcshrtname,
  markclr.color as markclrcolor,
  v1.dtrcvtm,
  v1.dtgtwid,
  v1.dtriptype,
  v1.dlatitudedeg,
  v1.dlongitudedeg,
  v1.dspeedkmph,
  v1.dheadingdeg
from dvc as dvc1
left join dvcgrp on dvcgrp.id = dvc1.dvcgrpid
left join markclr on markclr.id = dvcgrp.markclrid
left join vhsrdt v1 on v1.dvcid = dvc1.id 
left join lateral (select max(v2.dtrcvtm) as max_dtrcvtm
                   from vhsrdt v2 
                   where v2.dvcid = v1.dvcid
                  ) as dt on dt.max_dtrcvtm = v1.dtrcvtm
...