Повышение производительности MYSQL QUERY с участием профсоюзов - PullRequest
2 голосов
/ 21 июня 2019

Утилита Golang, которая может уменьшать количество точек данных в день в таблице с историческими данными.

Диапазон записей составляет от 20 до 400 записей в день.всего существует как минимум 100 миллионов записей.

Утилита может урезать ее до n записей в день до указанной даты.(n может варьироваться от 1 до 300 записей в день)

Я использую следующий метод:

ШАГ 1:

CREATE TABLE main_table_tmp LIKE main_table;

ШАГ 2:

ALTER TABLE main_table_tmp ADD COLUMN timekey INT;

ШАГ 3:

INSERT INTO main_table_tmp 
SELECT * FROM (
  SELECT *,FLOOR(UNIX_TIMESTAMP(column_name)/((1440/2)*60)) AS timekey 
  FROM main_table
  WHERE column_name <= '2018-01-01' 
  GROUP BY timekey
) m 
UNION ALL 
(SELECT * ,0 As timekey FROM main_table where column_name > 'date') ;

ШАГ 4:

ALTER TABLE main_table_tmp DROP COLUMN timekey;

DROP TABLE maintable;

RENAME TABLE maintable_tmp TO maintable;

Я добиваюсь вышеизложенного с помощью golang.

func somefuncname(){

  ---- 
  ----
  ----
  q := "CREATE TABLE " + *tablename + "_tmp LIKE " + *tablename + ";"
  rows, err := db.Query(q)
  if err != nil {
  fmt.Println(err)
  }
//--ALTER ADD timekey
//--INSERT INTO SELECT *....
//--ALTER DROP timekey ,DROP table and rename

}

Текущее время ответа на этот запрос очень медленное

Некоторые результаты: Всего записей: 2 миллиона
Время выполнения: 180 секунд

Это на 16 ГБ ОЗУ. Процессор очень медленный, когда он развернут в низкокачественной системе

У меня есть шагипотребовалось решить это:

  1. Посмотрел индексы всех таблиц.Попробовал удалить индекс и запустить утилиту.Удаление индексов ускорило работу утилиты на 5 секунд, что также немного.

  2. Выполнение утилиты поэтапно: если общее количество записей превышает 1 миллион, запускайте утилиту по миллиону за раз

Но после всех этих попыток похоже, что основная проблема заключается в самом запросе.

Это просто недостаточно быстро.Мне просто нужен способ повысить эффективность запроса

Любая помощь оценена, спасибо, ребята !!

1 Ответ

3 голосов
/ 21 июня 2019

Почему мы добавляем timekey, а затем отбрасываем его? Быстрое добавление его в пустую таблицу, но удаление его из таблицы после заполнения, это похоже на дополнительную копию таблицы. Это ненужная работа, если она нам не нужна.

Мы можем сделать GROUP BY для выражения; это выражение не должно появляться в списке SELECT. Например:

SELECT t.*
  FROM main_table t
 WHERE t.column_name <= '2018-01-01'
 GROUP 
    BY FLOOR(UNIX_TIMESTAMP(t.column_name)/((1440/2)*60))

(Обратите внимание, что этот запрос вызовет ошибку, если в sql_mode включено ONLY_FULL_GROUP_BY; это отключает специфичное для MySQL расширение, позволяющее выполнить запрос.)

Без некоторых определений таблиц (включая механизм хранения, типы данных столбцов, индексы) и без вывода EXPLAIN, мы только догадываемся.

Но некоторые предложения:

Удалите вторичные индексы в пустой заполняемой таблице и добавьте их после загрузки таблицы.

Я бы избегал СОЮЗА. Учитывая, что один из операторов SELECT имеет предикат column_name, а другой - предикат совершенно другого столбца date, мы хотим разделить операторы SELECT.

CREATE TABLE main_table_tmp LIKE main_table
;

-- for performance, remove secondary indexes, leave just the cluster index
ALTER TABLE main_table_tmp 
    DROP INDEX noncluster_index_1
  , DROP INDEX noncluster_index_2
  , ...
;

-- for performance, have a suitable index available on main_table 
-- with `column_name` as the leading column
INSERT INTO main_table_tmp 
SELECT h.*
  FROM main_table h
 WHERE h.column_name <= '2018-01-01'
 GROUP 
    BY FLOOR(UNIX_TIMESTAMP(h.column_name)/((1440/2)*60))
;

-- for performance, have a suitable index available on main_table
-- with `date` as the leading column
INSERT INTO main_table_tmp
SELECT c.*
  FROM main_table
 WHERE c.date > '????-??-??'
;

-- add secondary indexes 
ALTER TABLE maint_table_tmp
    ADD UNIQUE INDEX noncluster_index_1 (fee,fi,fo)
  , ADD INDEX noncluster_index_2 (fum)
  , ...
;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...