Подтвердить что ты не робот

Мониторинг хода выполнения MySQL Long Long

Чтобы предисловие к моему вопросу, я понимаю, что нет никакой непосредственной поддержки для чего-то подобного. То, что я ищу, - это любой вид работы или свернутый вывод, который принесет мне полупорядочный результат.

Я работаю с довольно большим кластером MySQL (таблицы > 400 миллионов строк), используя механизм кластера.

Кто-нибудь знает о способе либо напрямую извлекать или иначе получить несколько (или лучше) точные указания о прогрессе через длинный запрос в mysql? У меня есть несколько запросов, которые могут занять до 45 минут, и мне нужно определить, если мы обработаем 10% или 90%.

EDIT:

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

SELECT `userId`
FROM    `openEndedResponses` AS `oe`
WHERE
    `oe`.`questionId` = 3 -- zip code
    AND (REPLACE( REPLACE( `oe`.`value`, ' ', '' ), '-', '' ) IN ( '30071', '30106', '30122', '30134', '30135', '30168', '30180', '30185', '30187', '30317', '30004' ));

Этот запрос выполняется против одной таблицы с ~ 95 миллионами строк. Для выполнения запроса требуется 8 секунд, а еще 13 - для передачи данных (всего 21 сек). Учитывая размер таблицы и тот факт, что используются функции манипуляции строкой, я бы сказал, что она работает довольно быстро. Тем не менее, для пользователя, он все еще на 21 секунду появляется либо застрял, либо простаивает. Некоторый признак прогресса был бы идеальным.

4b9b3361

Ответ 1

Пока - для моей конкретной ситуации - для этого, похоже, не существует реального решения. Так как я не могу разбить мой запрос на несколько более мелких и сначала доказать, что он неэффективен для select count(*), а затем запустить "реальный" запрос (удваивает время выполнения и без того болезненно медленного запроса), ни одно из обходных решений не кажется жизнеспособным. Возможно, в ближайшее время MySQL поддержит что-то вроде этого

Ответ 2

Я смог оценить что-то вроде этого, запросив количество обрабатываемых строк, а затем разбив обработку на цикл, работая только с подмножеством из всех строк за раз.

Полный цикл был довольно активным, но основная логика выглядела так:

SELECT @minID = Min(keyColumn) FROM table WHERE condition
SELECT @maxID = Max(keyColumn) FROM table WHERE condition
SELECT @potentialRows = (@maxID - @minID) / @iterations

WHILE @minID < @maxID
BEGIN
    SET @breakID = @minID + @potentialRows
    SELECT columns FROM table WITH (NOLOCK, ...)
    WHERE condition AND keyColumn BETWEEN @minID AND @breakID

    SET @minID = @breakID + 1
END

Обратите внимание, что это лучше всего работает, если идентификаторы распределены равномерно.

Ответ 3

Я не думаю, что mysql поддерживает. Я уверен, что MySQL не поддерживает никаких указаний о ходе выполнения запросов. Единственное решение - оптимизировать/разбить запросы. Выбор можно разделить по id, как предлагал Dour High Arch. Вот запрос из таблицы 33 milion row:

mysql> SELECT SQL_NO_CACHE min(id), max(id) FROM `urls`;
+---------+----------+
| min(id) | max(id)  |
+---------+----------+
|    5000 | 35469678 |
+---------+----------+
1 row in set (0.00 sec)

Лучше использовать целое число по крайней мере для поля даты для разделения. Он должен быть основным или уникальным индексом и не должен допускать нулевые значения.

Ответ 4

Если это сложный запрос, который вы пытаетесь, команда EXPLAIN SQL или MySQL Query Analyzer может помочь понять, что происходит. Если это просто большой запрос, вы можете попытаться создать временную таблицу с помощью SELECT INTO и/или с помощью предложений LIMIT/OFFSET в запросах SELECT. Если вы используете LIMIT/OFFSET в исходных таблицах, вам может потребоваться установить уровень транзакции на сериализуемый, IIRC, чтобы вы получали согласованное чтение при повторном анализе данных. Если вы сначала создаете временную таблицу, эта таблица должна оставаться неизменной независимо.

Ответ 5

Вот что вам нужно сделать, чтобы улучшить следующий запрос:

SELECT `userId`
FROM    `openEndedResponses` AS `oe`
WHERE
    `oe`.`questionId` = 3 -- zip code
    AND (REPLACE( REPLACE( `oe`.`value`, ' ', '' ), '-', '' ) IN ( '30071', '30106', '30122', '30134', '30135', '30168', '30180', '30185', '30187', '30317', '30004' ));

Вам нужно убедиться, что oe.questionId проиндексирован; Вы должны убедиться, что oe.value не имеет места во всей таблице, когда oe.questionId равно 3; предполагая, что 4 или 5 могут быть, допустим, названиями городов, где вы все еще хотите разрешить пробелы.

Сделав это, вы сможете удалить все REPLACE, что позволит MySQL использовать индекс в oe.value.

MySQL затем объединит оба индекса и даст вам результат намного быстрее, с точки зрения обработки.

В случае, если у вас много повторяющихся userId; вы захотите их сгруппировать; таким образом, что записи из индекса немедленно отбрасываются. Вам все равно нужно сканировать весь объединенный индекс; но размер набора результатов займет меньше времени; намного меньше 13 секунд!

Сделайте снимок и держите нас в курсе результатов

Best!

Ответ 6

Как насчет разметки таблицы mysql, чтобы вы могли распространять нагрузку на чтение/запись. Посмотрите на попытку ограничить каждый раздел до 50 миллионов строк (очевидно, зависит от вашего оборудования).

Ответ 7

Я знаю, что это старый вопрос, но я искал аналогичный ответ, пытаясь выяснить, насколько дольше мое обновление займет запрос в 250 м строк.

Если вы запустите:

SHOW ENGINE INNODB STATUS \G

Затем в разделе ОПЕРАЦИИ найдите транзакцию, рассмотрите этот раздел:

---TRANSACTION 34282360, ACTIVE 71195 sec starting index read
mysql tables in use 2, locked 2
1985355 lock struct(s), heap size 203333840, 255691088 row lock(s), undo log entries 21355084

Важным битом является "отменить записи журнала". Для каждой обновленной строки в моем случае она, казалось, добавляла запись журнала отмены (через несколько секунд пробуя запустить ее и посмотреть, сколько было добавлено).

Если вы перейдете к концу отчета о статусе, вы увидите следующее:

Number of rows inserted 606188224, updated 251615579, deleted 1667, read 54873415652
0.00 inserts/s, 1595.44 updates/s, 0.00 deletes/s, 3190.88 reads/s

Здесь мы видим, что применяются обновления скорости 1595.44 строки в секунду (хотя, если вы выполняете другие запросы обновления в тандеме, эта скорость может быть разделена между вашими запросами).

Итак, я знаю, что 21 м были обновлены (250 м-21 м) 229 м строк, оставшихся до конца.

229 000 000/1600 = 143,125 секунд (143,125/60)/60 = 39,76 часа, чтобы пойти

Таким образом, казалось бы, я могу закрутить большие пальцы еще пару дней. Если этот ответ не соответствует действительности, в этом случае я обнов его когда-нибудь раньше!