MySQL Long Query Progress Monitoring - PullRequest
       5

MySQL Long Query Progress Monitoring

46 голосов
/ 29 марта 2011

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

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

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

РЕДАКТИРОВАТЬ:

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

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 секунд, кажется либо застрял или простаивает.Некоторые признаки прогресса были бы идеальными.

Ответы [ 9 ]

24 голосов
/ 25 июля 2017

Я знаю, что это старый вопрос, но я искал аналогичный ответ, пытаясь выяснить, сколько времени займет мое обновление для запроса на 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 часа вперед

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

7 голосов
/ 29 марта 2011

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

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

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

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

2 голосов
/ 09 апреля 2012

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

2 голосов
/ 30 марта 2011

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

2 голосов
/ 30 марта 2011

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

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

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

1 голос
/ 19 июля 2018

Существует многообещающий ответ на этот старый вопрос, который я нашел здесь , написанный бароном Шварцем.Это не точное и полное решение, но оно предоставляет некоторый объективный материал для оценок, , если вы только выполняете этот запрос и ничего больше на своем сервере .

Вы запускаете эту команду пока запрос уже выполняется :

mysqladmin extended -r -i 10 | grep Handler
  • , что 10 - это количество секунд, после которого команда повторяется, поэтому дождитесь обновления
  • добавьте что-то вроде -u root -p, если вам нужно аутентифицировать
  • , если вы точно знаете, какой обработчик вы ищете, вы можете сделать grep более сфокусированным, например, Handler_read_rnd_next, кажется, подходит дляSELECT
  • игнорировать первый выход, использовать второй и последующие
  • использовать Ctrl-C для выхода

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

Бесплатный дополнительный совет: команда, похоже, не входит в историю Bash (возможно,из-за выхода с помощью Ctrl-C вы можете добавить его туда вручную с помощью history -s mysqladmin extended -r -i 10 -u root -p | grep Handler

1 голос
/ 10 ноября 2015

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

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 могут быть, скажем, названиями городов, где вы все еще хотите разрешить пробелы.

Сделав это, вы сможете удалить все ЗАМЕНЫ, что позволит MySQL использовать индекс в oe.value.

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

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

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

Лучший!

0 голосов
/ 04 августа 2018

Если ваш запрос включает в себя линейное сканирование большой таблицы, вы часто можете получить превосходную оценку, запустив pmonitor в файле, содержащем эту таблицу. Включите параметр --update, поскольку MySQL открывает файлы таблиц в режиме обновления.

Пример:

$ sudo pmonitor --update --file=/home/mysql/ghtorrent/commits.MYD --interval=5

/home/mysql/ghtorrent/commits.MYD 31.66%
/home/mysql/ghtorrent/commits.MYD 33.16% ETA 0:03:42
/home/mysql/ghtorrent/commits.MYD 34.85% ETA 0:03:24
/home/mysql/ghtorrent/commits.MYD 36.43% ETA 0:03:32
/home/mysql/ghtorrent/commits.MYD 38.36% ETA 0:03:12
/home/mysql/ghtorrent/commits.MYD 40.21% ETA 0:03:01
/home/mysql/ghtorrent/commits.MYD 41.95% ETA 0:02:54
[...]
/home/mysql/ghtorrent/commits.MYD 92.01% ETA 0:00:24
/home/mysql/ghtorrent/commits.MYD 93.85% ETA 0:00:18
/home/mysql/ghtorrent/commits.MYD 95.76% ETA 0:00:12
/home/mysql/ghtorrent/commits.MYD 97.60% ETA 0:00:07
/home/mysql/ghtorrent/commits.MYD 98.83% ETA 0:00:03
/home/mysql/ghtorrent/commits.MYD 100% ETA 0:00:00

Если вы не знаете файл для мониторинга, запустите pmonitor с параметром --diff. Это покажет вам файл (ы), где достигнут прогресс.

Пример

$ sudo pmonitor --update -diff --command=mysqld -i 60
[...]
/home/mysql/ghtorrent/projects.MYD      22.41% ETA 2:01:41
/home/mysql/ghtorrent/projects.MYD      23.13% ETA 1:53:23
/home/mysql/ghtorrent/projects.MYD      23.84% ETA 1:50:27
0 голосов
/ 08 ноября 2013

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...