2014-09-25 2 views
-2

У меня есть cronjob, который выполняет длительный запрос каждые 5 минут. Этот запрос не критичен по времени, он занимает около 30 секунд.Длительный несущественный запрос замедляет другие запросы

Проблема в том, что во время выполнения запроса все остальные запросы выполняются значительно медленнее.

Запрос очень прост (нет объединений, использует индекс и т. Д.), Но читает много данных (1,5 мил строк, около 150 байт данных в строке).

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

Есть ли способ дросселировать этот конкретный запрос?

Edit: Запрос на самом деле просто:

SELECT field1,field2 FROM table; 

Edit 2: Хорошо, жаль это говорить, но каждый один из вас отсутствует пункт здесь. Я спрашиваю, могу ли я сжать запрос, и все ответы, которые я получаю, вообще не затрагивают вопрос. Вы все говорите мне изменить cronjob (я знаю, что могу), запустите его из cli (я не хочу), получая данные в кусках и т. Д.

Опять же я спрашиваю конкретно Могу ли я каким-то образом выполнить Запрос MySQL SELECT как «не важно», чтобы он не украл все ресурсы из других запросов?

Извините, если это звучит как основной тирады, я ценю, что вы нашли время, чтобы помочь :)

+0

Почему бы вы возвращение 1,5 миллиона строк в работе, которая выполняется каждые 30 секунд? Где идут строки? –

+0

Работа выполняется каждые 5 минут, запрос занимает около 30 секунд. Мне нужны данные, чтобы рассчитать материал (слишком долго объяснять здесь, но я * делаю * нужны все данные). – smoove

+0

Да, но каковы данные? Перемещение 1,5 миллиона строк почти наверняка является причиной замедления и вряд ли улучшится, если вы не сможете обойти это перемещение (IE, если он вернется в mysql, тогда вы могли бы использовать INSERT ... SELECT?). – Giles

ответ

2

Google дал this ответ на то, что похоже на ту же проблему, с которой вы сталкиваетесь. В статье описывается запрос, который читает всю таблицу, и использует много операций ввода-вывода; решение состоит в том, чтобы читать 1000 строк за раз, а затем спать в течение времени, затраченного на извлечение этих строк.

Я не уверен, что это исправит вашу проблему, но, похоже, это заслуживающее доверия решение.

ниже код копируется из ссылки и немного изменен, чтобы ответить на ваш вопрос:

SELECT 
    field1, field2, 
    CASE 
     WHEN (@row_counter := @row_counter + 1) IS NULL THEN NULL 
     WHEN @row_counter % 1000 = 0 THEN 
     CASE 
      WHEN (@time_now := SYSDATE()) IS NULL THEN NULL 
      WHEN (@time_diff := (TIMESTAMPDIFF(SECOND, @chunk_start_time, @time_now))) IS NULL THEN NULL 
      WHEN SLEEP(@time_diff) + test.prove_it(CONCAT('will sleep for ', @time_diff, ' seconds')) IS NULL THEN NULL 
      WHEN (@chunk_start_time := SYSDATE()) IS NULL THEN NULL 
      ELSE 0 
     END 
     ELSE 0 
    END AS rental_id, 
    TIMESTAMPDIFF(DAY, rental_date, return_date) AS rental_days 
FROM 
    table, 
    (SELECT @row_counter := 0) sel_row_counter, 
    (SELECT @chunk_start_time := NOW()) sel_chunk_start_time 
; 
+0

Спасибо, это работает отлично! – smoove

-1

Если вы можете назвать ваш запрос полностью из командной строки (и при условии, что вы работаете на Linux/UNIX/OS X система), вы можете понизить приоритет планирования с использованием nice, например:

nice -n 19 mysql -u vivek -p -e 'SELECT COUNT(*) FROM quotes' cbzquotes

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

+0

жаль, что я не могу, запрос является частью cronjob (написанный на php), и мне нужны данные в скрипте. – smoove

+0

Кажется мне все еще возможно через shell_exec, нет? –

+0

И/или читать из файла. (Я думаю, что shell_exec имеет дело с выводом команды в виде одной строки, а 1,5 миллиона записей будут сильно удачными. –

1

Вы можете создать петлю в PHP и получить данные в партиях, например, 100 000 строк, со сном в несколько миллисекунд между каждой партией. Не идеально, но это даст другим запросам немного больше шансов.

1

Извлечение пяти мегаресурсов с сервера MySQL клиенту (процесс cronjob), выдающий этот запрос за тридцать секунд, является достойной производительностью. Вы не собираетесь улучшать его более чем незначительно.

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

Причина, по которой ваша система замедляется, заключается в том, что MySQL пытается вернуть согласованные результаты в вашу операцию SELECT. Он ставит в очередь или удерживает вставки и обновления для вашего стола, пока он подталкивает ваши результаты к вашему клиенту.

Как вы можете победить эту проблему? Лучший способ - исправить процесс cronjob. Идеальная ситуация заключалась бы в том, чтобы выполнять вычисления в системе баз данных, а не в cronjob. То есть, что-то вроде этого.

SELECT SUM(column) AS colsum, MAX(column2) AS colmax, DATE(timecolumn) AS day 
    FROM table 
GROUP BY DATE(timecolumn) 

Вы не сказали нам, что ваш cronjob делают с этими пяти миллионов строк, поэтому я просто показывать этот запрос в качестве примера. Эта вещь обрабатывает таблицу, но возвращает FAR меньше строк. Он также может быть оптимизирован.

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

Другим решением является переключение таблиц в MyISAM. Это избавляет от транзакционной семантики. Это может испортить остальную часть вашего приложения.

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

Теперь, возможно, вам не разрешено менять cronjob или инфраструктуру. Если вы не можете выполнить какие-либо из этих алгоритмических или инфраструктурных изменений, у вас может быть кандидат на http://thedailywtf.com/. Магии нет, что делает массовую передачу данных в сотни раз быстрее.

+1

Что такое * megarow *? – Kermit

+0

Мегауров - это тысяча килограммов, а килогород - тысяча строк. –

+0

Итак, что такое yottarow? – Kermit

Смежные вопросы