Вопрос об утверждении "UNION ALL", MYSQL - PullRequest
0 голосов
/ 14 сентября 2018

Недавно я написал SQL-запрос, подобный следующему:

SELECT DESCR, ip, CPUCpuUtil_day, CPUWio_day
FROM (SELECT res.res_descr DESCR,
node.ip ip,
(ifnull(ROUND(max(CASE WHEN kpi_no = 100000041 THEN k.valuemax END), 2), 0)) CPUCpuUtil_day,
(ifnull(ROUND(max(CASE WHEN kpi_no = 100000041 THEN k.valuemax END), 2), 0)) CPUWio_day
      FROM res_object res
      LEFT JOIN (SELECT res.res_id, p.kbp, p.valuemax, p.time_id, p.kpi_no
      FROM res_object res
      LEFT JOIN pm_day_p_reshost p ON p.kbp = res.res_id
      AND (p.kpi_no = 100000041 OR p.kpi_no = 100000041) WHERE res.classname = 'ResHost'
      AND p.time_id >= '20180913'
      AND p.time_id < '20180914') k ON k.res_id = res.res_id, res_node node, res_multiselect rs, res_dim_os os
      WHERE rs.multiselect_id = res.multiselect_id
      AND node.res_id = res.res_id
      AND os.os_id = node.os_id
      AND OS.DESCR = 'Linux'
      GROUP BY res.res_descr, node.ip) x

Этот запрос займет больше одной минуты, чтобы показать мне данные из-за огромных данных. Но если я добавлю инструкцию UNION ALL: UNION ALL SELECT 1 res_id, 1 valuemax, 1 kbp, 1 time_id, 1 kpi_no или инструкцию UNION ALL, которая получит 0 строк после AND p.time_id >= '20180913' AND p.time_id < '20180914', этот запрос будет выполнен через три секунды.
Так почему это может быть? Почему это так быстро после добавления такого оператора UNION ALL?
Интересно, принцип этого.
Любой ответ будет с благодарностью.

1 Ответ

0 голосов
/ 14 сентября 2018

Это всего лишь предложение (но сложное для комментария)

при поиске исходного запроса кажется, что у вас странная кодировка

, что означает столбец, разделенный запятой в k ON k.res_id = res.res_id, узел res_node, res_multiselect rs, res_dim_os os

при условии, что вы смешиваете explict join и implict join sintax basec при условии условия.Вы должны использовать только синтаксис явного соединения, а не более старый синтаксис имплика

, и у вас есть условие WHERE для столбца левой объединенной таблицы во внутреннем левом соединении, если вы используете где для таблиц с левым соединением они работают как INNER JOIN ..
(и вы выбираете два одинаковых значения с разными псевдонимами столбцов CPUCpuUtil_day и CPUWio_day), на ваш запрос может быть изменен рефакторинг как

    SELECT DESCR
        , ip
        , CPUCpuUtil_day
        , CPUWio_day
    FROM (
        SELECT res.res_descr DESCR
            , node.ip ip
            , (ifnull(ROUND(max(CASE WHEN kpi_no = 100000041 
                            THEN k.valuemax END), 2), 0)) CPUCpuUtil_day
            , (ifnull(ROUND(max(CASE WHEN kpi_no = 100000041 
                            THEN k.valuemax END), 2), 0)) CPUWio_day
         FROM res_object res
         LEFT JOIN (
            SELECT res.res_id
                , p.kbp
                , p.valuemax
                , p.time_id
                , p.kpi_no
            FROM res_object res
            INNER JOIN pm_day_p_reshost p ON p.kbp = res.res_id
                AND (p.kpi_no = 100000041 OR p.kpi_no = 100000041) 
                    AND res.classname = 'ResHost'
                        AND p.time_id >= '20180913'
                            AND p.time_id < '20180914'
            ) k ON k.res_id = res.res_id 
         INNER JOIN res_multiselect rs ON rs.multiselect_id = res.multiselect_id
         INNER JOIN res_node node ON  node.res_id = res.res_id
         INNER JOIN res_dim_os os ON os.os_id = node.os_id
            AND OS.DESCR = 'Linux'
        GROUP BY res.res_descr, node.ip 
    ) x
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...