MySQL первое / последнее значение и расчеты с предыдущим значением - PullRequest
0 голосов
/ 26 марта 2020

У меня огромные таблицы со строками данных за каждую минуту. Некоторые столбцы рассчитываются с разницей [последнее значение интервала] - [значение последнего интервала перед] . Но есть ли способ ускорить запрос? Уже есть основной и индекс даты. Не должно быть никаких дополнительных индексов. В настоящее время запрос выполняется около 11 секунд для примерно 500 000 строк.

Проблема близка к вычислениям с функцией DATE_SUB () .

MySQL: 10.1.44- MariaDB-0ubuntu0.18.04.1

PHP: 7.2.24-0ubuntu0.18.04.3

*id* || *select_type*      || *table*   || *type* || *possible_keys* || *key* || *key_len* || *ref* || *rows* || *filtered* || *Extra*
1    || PRIMARY            || a10       || ALL    || date            ||       ||           ||       || 513754 || 21.86      || Using where; Using temporary; Using filesort
4    || DEPENDENT SUBQUERY || table_min || index  || date            || date  || 5         ||       || 1      || 100.00     || Using where
3    || DEPENDENT SUBQUERY || table_min || index  || date            || date  || 5         ||       || 1      || 100.00     || Using where
2    || DEPENDENT SUBQUERY || table_min || index  || date            || date  || 5         ||       || 1      || 100.00     || Using where

Запрос:

EXPLAIN EXTENDED 
SELECT  SQL_CALC_FOUND_ROWS tm.date,
CAST(SUBSTRING_INDEX(GROUP_CONCAT(tm.DB223_DBD10_float ORDER BY  tm.date DESC),
                ",", 1) AS double
    ) AS `10-44-2`,
                CAST(SUBSTRING_INDEX(GROUP_CONCAT(tm.DB223_DBD14_float ORDER BY  tm.date DESC),
                ",", 1) AS double) AS `10-45-3`, MIN(tm.DB221_DBD218_float
                    ) AS `10-2-4`,
                MAX(tm.DB221_DBD218_float) AS `10-2-5`, MIN(tm.DB221_DBD222_float) AS `10-3-6`,
MAX(tm.DB221_DBD222_float) AS `10-3-7`, MIN(tm.DB221_DBD278_float) AS `10-4-8`,
MAX(tm.DB221_DBD278_float) AS `10-4-9`, (CAST(SUBSTRING_INDEX(GROUP_CONCAT(tm.DB222_DBD10_integer
                                    ORDER BY  tm.date DESC), ",", 1) AS double) - 
            (
                SELECT  DB222_DBD10_integer
                    FROM  table_min
                    WHERE  date <= DATE_SUB(tm.date, INTERVAL 1 DAY)
                    ORDER BY  date DESC
                LIMIT  1)
   ) AS `10-18-10`,
                    (CAST(SUBSTRING_INDEX(GROUP_CONCAT(tm.DB222_DBD46_integer
       ORDER BY  tm.date DESC),
                        ",", 1) AS double) - (
                SELECT  DB222_DBD46_integer
                    FROM  table_min
                    WHERE  date <= DATE_SUB(tm.date, INTERVAL 1 DAY)
                    ORDER BY  date DESC
                LIMIT  1)
                    ) AS `10-36-11`,
                    (CAST(SUBSTRING_INDEX(GROUP_CONCAT(tm.DB222_DBD50_integer
       ORDER BY  tm.date DESC),
                        ",", 1) AS double
                          ) - (
                SELECT  DB222_DBD50_integer
                    FROM  table_min
                    WHERE  date <= DATE_SUB(tm.date, INTERVAL 1 DAY)
                    ORDER BY  date DESC
                LIMIT  1)
                    ) AS `10-37-12`,
                CAST(SUBSTRING_INDEX(GROUP_CONCAT(tm.DB223_DBD124_float
       ORDER BY  tm.date DESC),
                ",", 1) AS double
                    ) AS `10-47-13`,
                CAST(SUBSTRING_INDEX(GROUP_CONCAT(tm.DB223_DBD120_float
       ORDER BY  tm.date DESC),
                ",", 1) AS double
                    ) AS `10-46-14`,
                CAST(SUBSTRING_INDEX(GROUP_CONCAT(tm.DB223_DBD128_float
       ORDER BY  tm.date DESC),
                ",", 1) AS double
                    ) AS `10-48-15`,
                CAST(SUBSTRING_INDEX(GROUP_CONCAT(tm.DB223_DBD132_float
       ORDER BY  tm.date DESC),
                ",", 1) AS double
                    ) AS `10-49-17`,
                CAST(SUBSTRING_INDEX(GROUP_CONCAT(tm.DB223_DBD136_float
       ORDER BY  tm.date DESC),
                ",", 1) AS double
                    ) AS `10-50-18`,
                CAST(SUBSTRING_INDEX(GROUP_CONCAT(tm.DB223_DBD140_float
       ORDER BY  tm.date DESC),
                ",", 1) AS double
                    ) AS `10-51-19`,
                CAST(SUBSTRING_INDEX(GROUP_CONCAT(tm.DB223_DBD144_float
       ORDER BY  tm.date DESC),
                ",", 1) AS double
                    ) AS `10-52-21`,
                CAST(SUBSTRING_INDEX(GROUP_CONCAT(tm.DB223_DBD148_float
       ORDER BY  tm.date DESC),
                ",", 1) AS double
                    ) AS `10-53-22`,
                CAST(SUBSTRING_INDEX(GROUP_CONCAT(tm.DB223_DBD310_float
       ORDER BY  tm.date DESC),
                ",", 1) AS double
                    ) AS `10-54-24`,
                CAST(SUBSTRING_INDEX(GROUP_CONCAT(tm.DB223_DBD314_float
       ORDER BY  tm.date DESC),
                ",", 1) AS double
                    ) AS `10-55-25`,
                    (CAST(SUBSTRING_INDEX(GROUP_CONCAT(tm.DB223_DBD310_float
       ORDER BY  tm.date DESC),
                        ",",
                                                ",", 1) AS double),NULL)) AS `10-0-26`,
                        1) AS double)/NULLIF(CAST(SUBSTRING_INDEX(GROUP_CONCAT(tm.DB223_DBD314_float
       ORDER BY  tm.date DESC),
CAST(SUBSTRING_INDEX(GROUP_CONCAT(tm.DB221_DBD538_float
       ORDER BY  tm.date DESC),
                ",", 1) AS double) AS `10-31-27`,
                MIN(tm.DB221_DBD326_float) AS `10-9-28`,
                MAX(tm.DB221_DBD326_float) AS `10-9-29`,
                MIN(tm.DB221_DBD450_float) AS `10-29-30`,
                MAX(tm.DB221_DBD450_float) AS `10-29-31`,
                MIN(tm.DB221_DBD406_float) AS `10-27-32`,
                MAX(tm.DB221_DBD406_float) AS `10-27-33`,
                MIN(tm.DB221_DBD562_float) AS `10-41-34`,
                MAX(tm.DB221_DBD562_float) AS `10-41-35`
    FROM  table_min AS tm WHERE  tm.date>="2020-01-01 00:00"
      AND  tm.date<="2020-01-31 23:59:59"
    GROUP BY  YEAR(tm.date), MONTH(tm.date), DAY(tm.date)
    ORDER BY  tm.date
    LIMIT  0,20

SQL dump данных за этот год: https://www.tds-net.de/table_min.zip

1 Ответ

0 голосов
/ 28 марта 2020
  • 2 Уникальные ключи. Возможно, вы можете избавиться от id и повысить date до ПК?

  • SQL_CALC_FOUND_ROWS сил, проходящих через все выбранные строки. Можете ли вы избавиться от этого?

  • LIMIT 0,20 - Это прелюдия к "нумерации страниц"? Если это так, гораздо эффективнее запомнить, где вы остановились .

  • GROUP BY YEAR(tm.date), MONTH(tm.date), DAY(tm.date) ORDER BY tm.date, вероятно, приведет к двум видам. (См. EXPLAIN FORMAT=JSON SELECT ..., чтобы проверить. Это, я думаю, позволит избежать второго рода, будет проще, но, возможно, не намного быстрее: GROUP BY DATE(tm.date) ORDER BY DATE(tm.date). Обратите внимание, что теперь они говорят то же самое, тем самым избегая дополнительной сортировки.

  • SELECT tm.date ... GROUP BY ... не подходит, измените его тоже.

  • Сначала получите данные, , затем pivot. (Это будет задействовать другой уровень вложенности SELECTs.)

  • Это может было бы лучше получить 3 значения из операторов, как в одном запросе. Но я не знать лучший способ сложить его обратно.

                SELECT  DB222_DBD10_integer
                    FROM  table_min
                    WHERE  date <= DATE_SUB(tm.date, INTERVAL 1 DAY)
                    ORDER BY  date DESC
                LIMIT  1)
    
...