Оптимизированная MySQl производительность запросов с объединением миллионов записей в таблицу - PullRequest
0 голосов
/ 18 июня 2020

Мне нужно вставить данные в одну временную таблицу, используя две таблицы Joins. Полное выполнение одной из моих таблиц с hist_data_app (примерно 300 миллионов) записей занимает 30 минут. Я хотел бы знать как я более оптимизировал запрос, чтобы сделать его быстрее.

Первая таблица содержит данные журнала изменений с некоторыми конкретными данными, а другая таблица содержит все данные, связанные с этим. Ниже приведен мой оператор создания обеих таблиц.

CREATE TABLE `hist_data_app` (
    `product_id` MEDIUMINT(8) UNSIGNED NOT NULL DEFAULT '0',
    `application_id` INT(10) UNSIGNED NOT NULL DEFAULT '0',
    `year_id` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0',
    `history_id` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0',
    `field_name` VARCHAR(60) NOT NULL COLLATE 'utf8_unicode_ci',
    `old_value` TEXT NOT NULL COLLATE 'utf8_unicode_ci',
    `new_value` TEXT NOT NULL COLLATE 'utf8_unicode_ci',
    `comments` TEXT NOT NULL,
    INDEX `ps` (`product_id`, `history_id`)
)

CREATE TABLE `histry_log` (
`history_id` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0',
`history_hash` CHAR(32) NOT NULL COLLATE 'utf8_unicode_ci',
`type` ENUM('products','brands','partnames','mc_partnames','applications') NOT NULL,
`user_id` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0',
`stamp` TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00',
`source` TINYINT(1) UNSIGNED NOT NULL DEFAULT '0',
`source_data` TEXT NOT NULL COLLATE 'utf8_unicode_ci',
`description` TEXT NOT NULL COLLATE 'utf8_unicode_ci',
PRIMARY KEY (`history_id`),
INDEX `Types` (`type`)

)

Это мой результат объяснения

EXPLAIN
SELECT DISTINCT a.product_id
              , a.history_id
              , a.comments
              , a.field_name
           FROM history_log b
           JOIN hist_data_app a
             ON a.history_id = b.history_id
          GROUP 
             BY product_id;

id select_type table type   possible_keys key     key_len ref                       rows      Extra
 1 SIMPLE      a     ALL    NULL          NULL    NULL    NULL                      278327646 Using temporary; Using filesort
 1 SIMPLE      b     eq_ref PRIMARY       PRIMARY 8       LONGBOW_data.a.history_id         1 Using index

таблица history_app_data

product_id  application_id year_id history_id
598865023   12813220945 92  16777304
598865023   12813220945 93  16777304
598865023   12813221222 93  16777304
598865023   12815428123 94  16777304
598865023   12813221833 92  16777304
598865023   12813221833 93  16777304
598865023   12815457549 92  16777304
598865023   12815457549 93  16777304
598865023   12815457549 94  16777304

Ответы [ 2 ]

0 голосов
/ 19 июня 2020
  • Запрос неверно сформирован; мы не должны обсуждать это, пока вы не исправите эту проблему. Прочтите о «only_full_group_by».
  • Возможно, никогда не «правильно» иметь и GROUP BY и DISTINCT в одном SELECT.
  • У вас есть «взорвать-взорваться» синдром. Это когда вы делаете JOIN, который строит большую временную таблицу, за которой следует GROUP BY, чтобы вернуться к тому, с чего вам, возможно, пришлось начать в одной из таблиц.
  • Набор результатов все еще огромный; что вы планируете делать с результатом?
  • У вас действительно должно быть PRIMARY KEY на каждом столе. Если это уникальный (history_id, product_id), сделайте его PK. (Обратите внимание, что я поменял местами порядок, как обсуждалось в других комментариях.)
  • year_id - Это нормализация YEAR? Не стоит. Просто укажите год в таблице; без дополнительного поиска.
  • Насколько велика другая таблица? (Возможно, я ошибаюсь в оптимизации.)
  • Это может дать вам те же данные, но намного быстрее:

    SELECT   a.product_id , a.history_id , a.comments , a.field_name
        FROM ( SELECT DISTINCT history_id FROM  history_log ) AS b
        JOIN  hist_data_app a  ON a.history_id = b.history_id
        GROUP BY  product_id;
    

Вы придется внести некоторые структурные изменения в таблицы; запланируйте время простоя.

Если вам нужны только данные о Hammers, покажите нам предложение WHERE, ограничивающее вывод. Оптимизация для этот запрос может значительно отличаться от 30-минутного запроса в вашем Вопросе!

Исправьте большую часть того, что я и другие предлагали, а затем вернитесь с новым Вопросом с fre sh схема, et c. (Эти вопросы и ответы становятся слишком беспорядочными, чтобы продолжать работу.)

0 голосов
/ 18 июня 2020

Судя по вашему ответу на мой комментарий, вы должны хорошо разбираться в том, что у вас есть сейчас. Поскольку ваше основное внимание будет уделяться одному продукту, ваша таблица Hist_Data_App имеет индекс product_id в первой позиции, что было бы тем, что вы хотите, но также поможет history_id для присоединения к таблице журнала. Просто добавьте предложение where и проверьте некоторые продукты.

SELECT 
      hd.product_id, 
      hd.history_id, 
      hd.comments, 
      hd.field_name
   FROM 
      hist_data_app hd
   where
      -- or whatever single product ID you want
      hd.product_id = 12345  

Теперь я не знаю, действительно ли вам нужен отдельный, но могу добавить его обратно без проблем. Поскольку вы не извлекаете какие-либо столбцы из таблицы журнала, вам даже не нужно присоединяться к этой таблице. Поскольку у вас нет агрегатов (таких как сумма, количество, среднее, и т. Д. c), вам не нужна группа по. Я думаю, у вас было это только в вашем образце запроса, когда вы вытаскивали ВСЕ свои данные, чтобы у вас не было возвращено 300 миллионов строк. продукты, которые ДЕЙСТВИТЕЛЬНО имеют наибольшее количество записей, чтобы увидеть, сколько времени для одного продукта, который буквально ДЕЙСТВИТЕЛЬНО имеет наибольшее количество записей. Чтобы получить это, вы можете захотеть

SELECT 
      hd.product_id,
      count(*) totalRecsPerProduct
   FROM 
      hist_data_app hd
   group by
      hd.product_id
   order by
      count(*) desc
   limit 10

. Это позволит получить 10 лучших продуктов с наибольшим количеством записей из ваших 300 миллионов, затем вы можете выполнить предыдущий запрос по ним и посмотреть, сколько РЕАЛЬНОГО времени потребуется. чтобы вернуть результаты. Я думаю, вы увидите, что производительность вашего одноразового продукта удовлетворительна.

...