Форум русской поддержки Joomla!® CMS
28.07.2017, 22:44:37 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
   
   Начало   Поиск Joomla 3.0 FAQ Joomla 2.5 FAQ Joomla 1.5 FAQ Правила форума Новости Joomla Реклама Войти Регистрация Помощь  
Основной курс по Joomla
Страниц: [1] 2 3 4 5 6 7   Вниз
  Добавить закладку  |  Печать  
Автор

Как разбить выполняемую работу на удобоваримые сервером куски?

 (Прочитано 1685 раз)
0 Пользователей и 1 Гость смотрят эту тему.
borro
Живу я здесь
******

Репутация: +21/-0
Offline Offline

Пол: Мужской
Сообщений: 1269


желаю вам счастья


« : 10.07.2017, 16:42:40 »

Здравствуйте!

Написал компонент, который медленно/долго работает, из-за чего некоторые его виды просто не открываются.

Если его вид dbdelete, который для отображения редактируемых данных выполняет запрос:
Код:
select `file_title`,`file_url`,`published`,`virtuemart_media_id`
from '#__virtuemart_medias m'
where file_type = 'product'
AND NOT EXISTS(SELECT virtuemart_media_id FROM #__virtuemart_product_medias WHERE virtuemart_media_id = m.virtuemart_media_id )

минуты через 2(и то не всегда) возвращает что-то на экран для дальнейших манипуляций
, то вид fsdelete(который по сути проверяет папки с полноразмерными и маленькими картинками и выводит те, что не упомянуты в БД) на боевом сервере просто через секунд 30 выдает белый экран. Файлов в каждой из папок на боевом сервере примерно по 23 000.

На локальном сервере, где мало файлов в файловой системе да и в базе, компонент работает.

Помогите, люди добрые, узнать как можно оптимизировать компонент и, быть может, разбить выполняемую им работу на куски, которые сможет выполнять сервер. Можно начать с вида fsdelete, который вовсе не открывается Azn
Наверно есть какие-то для это приёмы, ведь akeeba backup как-то работает, создавая архивы огромного сайта.

* com_vm3delpics.zip (24.27 Кб - загружено 1 раз.)
« Последнее редактирование: 10.07.2017, 16:59:44 от borro » Записан
robert
Профи
********

Репутация: +380/-14
Offline Offline

Пол: Мужской
Сообщений: 4167


« Ответ #1 : 10.07.2017, 19:40:06 »

Для запросов существует понятие LIMIT. А почему вид должен выполнять запросы в БД?
Записан
Arkadiy
Группа развития
*****

Репутация: +439/-0
Offline Offline

Пол: Мужской
Сообщений: 5422


Крепитесь, други.


« Ответ #2 : 10.07.2017, 20:00:31 »

Уберите подзапрос, сделайте либо отдельный запрос, либо внутреннее присоединение.
Записан
dmitry_stas
Профи
********

Репутация: +926/-6
Online Online

Сообщений: 9814



« Ответ #3 : 10.07.2017, 20:05:08 »

Наверно есть какие-то для это приёмы, ведь akeeba backup как-то работает, создавая архивы огромного сайта.
AJAX запросы. т.е. при каждом запросе выполняем какую-то маленькую часть работы, которая заведомо успевает выполнится, и возвращаем остаток сколько еще надо обработать. пока есть остаток - выводим прогрессбар, когда не остается - финальное сообщение.
Записан
borro
Живу я здесь
******

Репутация: +21/-0
Offline Offline

Пол: Мужской
Сообщений: 1269


желаю вам счастья


« Ответ #4 : 11.07.2017, 10:17:24 »

Доброе утро. Спасибо за отклик.
Для запросов существует понятие LIMIT. А почему вид должен выполнять запросы в БД?
А как просчитать, сколько ставить в LIMIT, чтобы сервер не поперхнулся и не ленился одновременно? Azn Я наверно неправильно выразился про вид, модель обращается и дает данные виду
« Последнее редактирование: 11.07.2017, 10:23:08 от borro » Записан
borro
Живу я здесь
******

Репутация: +21/-0
Offline Offline

Пол: Мужской
Сообщений: 1269


желаю вам счастья


« Ответ #5 : 11.07.2017, 10:18:15 »

Уберите подзапрос, сделайте либо отдельный запрос, либо внутреннее присоединение.
вы про EXISTS() чтобы убрать?
Записан
borro
Живу я здесь
******

Репутация: +21/-0
Offline Offline

Пол: Мужской
Сообщений: 1269


желаю вам счастья


« Ответ #6 : 11.07.2017, 10:21:49 »

AJAX запросы. т.е. при каждом запросе выполняем какую-то маленькую часть работы, которая заведомо успевает выполнится, и возвращаем остаток сколько еще надо обработать. пока есть остаток - выводим прогрессбар, когда не остается - финальное сообщение.
а как просчитать тот объем работы, который заведомо выполнится и чтобы не гонять в холостую? Этот AJAX код должен быть написан в виде? Не представляю пока, как он будет передавать данные на отображение. Может подскажите пример какого-то простого компонента, что смогу разобрать?
Записан
dmitry_stas
Профи
********

Репутация: +926/-6
Online Online

Сообщений: 9814



« Ответ #7 : 11.07.2017, 10:48:38 »

ну вы же сами упомянули про Akeeba Backup. она и есть пример, ее и разбирайте, там все есть.
Записан
SeBun
Практически профи
*******

Репутация: +184/-5
Offline Offline

Пол: Мужской
Сообщений: 3158


@SeBun48


« Ответ #8 : 11.07.2017, 15:03:05 »

А какая у вас задача стоит? Вы сделали запросы в цикле, как я понимаю, плюс не просто запрос, а с вложенным подзапросом. Посмотрите, сколько интераций выполняет цикл и посчитайте объем запросов в базу. И поймете, как делать нельзя. Возможно, перед циклом нужно сделать несколько запросов, взять значения и поместить в переменные, вместо того, что бы при каждой интерации делать запрос в базу. Опишите задачу, мы подскажем алгоритм.
Записан
borro
Живу я здесь
******

Репутация: +21/-0
Offline Offline

Пол: Мужской
Сообщений: 1269


желаю вам счастья


« Ответ #9 : 11.07.2017, 15:26:51 »

А какая у вас задача стоит? Вы сделали запросы в цикле, как я понимаю, плюс не просто запрос, а с вложенным подзапросом. Посмотрите, сколько интераций выполняет цикл и посчитайте объем запросов в базу. И поймете, как делать нельзя. Возможно, перед циклом нужно сделать несколько запросов, взять значения и поместить в переменные, вместо того, что бы при каждой интерации делать запрос в базу. Опишите задачу, мы подскажем алгоритм.
Компонент решает две главные задачи:
1. удаляет фотографии, которые не назначены товарам, но о них есть информация в базе данных. Это вид/модель/контроллер с названиями dbdelete
2. удаляет файлы в директориях с картинками, о которых нет упоминания в базе данных о том, что это используемые медиафайлы. Это вид/модель/контроллер с названиями fsdelete

В обоих случаях обращение в базу идёт единожды, но то ли сами sql-запросы тяжелы(что похоже в случае с dbdelete) для исполнения, то ли их построение времязатратно(что похоже в случае с fsdelete, поскольку сканирует папки на сервере с тоннами фотографий)
Записан
SeBun
Практически профи
*******

Репутация: +184/-5
Offline Offline

Пол: Мужской
Сообщений: 3158


@SeBun48


« Ответ #10 : 11.07.2017, 15:39:29 »

У вас 30 секунд в большинстве случаев на выполнение. Еще один вопрос: кто запускает задачу, пользователь или крон?
Записан
borro
Живу я здесь
******

Репутация: +21/-0
Offline Offline

Пол: Мужской
Сообщений: 1269


желаю вам счастья


« Ответ #11 : 11.07.2017, 15:45:45 »

Еще один вопрос: кто запускает задачу, пользователь или крон?
пользователь из панели компонента в админке.
« Последнее редактирование: 11.07.2017, 16:06:59 от borro » Записан
SeBun
Практически профи
*******

Репутация: +184/-5
Offline Offline

Пол: Мужской
Сообщений: 3158


@SeBun48


« Ответ #12 : 11.07.2017, 16:25:51 »

пользователь их панели компонента в админке.

Тогда все проще. Вам нужно запускать выполнение кода Ява-скриптом. Другими словами, клиенту загружается js-скрипт (это делается в виде), который запускает периодически php-скрипт на сервере, отдавая ему команды. Например, при первом запуске запускается счетчик, который считает время выполнения и определяет количество запросов, которое может выполнить скрипт за, к примеру, 10 секунд. Зная общее количество записей в базе можно посчитать примерное время выполнение кода. Пишите на JS форму, показывающую пользователю процент выполнения задачи. Можно попутно выводить информацию о том, сколько всего записей обработано из общего количества и сколько файлов удалено. Таким образом вы делите задачу на куски, к примеру, по 10 интераций вашего цикла за раз.  В цикле, как я понимаю, идет в базу запрос адреса, а затем вызывается метод проверки этого адреса. В магазине может быть десятки тысяч товаров, поэтому разбивать задачу нужно обязательно.
Записан
borro
Живу я здесь
******

Репутация: +21/-0
Offline Offline

Пол: Мужской
Сообщений: 1269


желаю вам счастья


« Ответ #13 : 11.07.2017, 17:51:17 »

Другими словами, клиенту загружается js-скрипт (это делается в виде), который запускает периодически php-скрипт на сервере, отдавая ему команды.
Эта тема про тоже, что вы предлагаете сделать?
Например, при первом запуске запускается счетчик, который считает время выполнения и определяет количество запросов, которое может выполнить скрипт за, к примеру, 10 секунд.
У меня запрос всегда один, он просто неподъемный для сервера. Вы про то сколько строк он успеет вытащить из базы за 10 секунд? А как это сделать, ограничить исполнение сформированного sql запроса временем?
В цикле, как я понимаю, идет в базу запрос адреса, а затем вызывается метод проверки этого адреса
Циклически к базе я не обращаюсь. Запрос у меня 1, он сразу возвращает данные обо всех удаляемых файлах, которые в цикле удаляются командой unlink. Также одним запросом удаляются строки по этим файлам в базе данных
Когда я проверяю со стороны файловой системы, есть ли такие файлы, что не упомянуты в базе, то тоже строится один большой селект, результаты которого потом отображаются в виде, если файлов в папке мало Azn
Записан
robert
Профи
********

Репутация: +380/-14
Offline Offline

Пол: Мужской
Сообщений: 4167


« Ответ #14 : 11.07.2017, 18:02:32 »

1 запрос и 2 минуты?
- проиндексируйте поля привязки
- разбейте запрос на 2, как посоветовали выше, или используйте LEFT JOIN ...WHERE ...IS NULL
Записан
Филипп Сорокин
Практически профи
*******

Репутация: +138/-4
Offline Offline

Пол: Мужской
Сообщений: 1807


« Ответ #15 : 11.07.2017, 18:55:35 »

Код:
AND NOT EXISTS(SELECT virtuemart_media_id FROM #__virtuemart_product_medias WHERE virtuemart_media_id = m.virtuemart_media_id )

Правильно, что у Вас запрос 2 минуты идёт, ведь благодаря этой клаузуле подзапрос делается для каждой позиции выборки, 100500 раз.
Записан
borro
Живу я здесь
******

Репутация: +21/-0
Offline Offline

Пол: Мужской
Сообщений: 1269


желаю вам счастья


« Ответ #16 : 11.07.2017, 18:58:57 »

поля проиндексированы.
переделываю на вариант с left join, протестирую...
"разбейте запрос на 2" - не понял, это как?
Записан
Филипп Сорокин
Практически профи
*******

Репутация: +138/-4
Offline Offline

Пол: Мужской
Сообщений: 1807


« Ответ #17 : 11.07.2017, 19:04:15 »

Цитировать
AND NOT EXISTS(SELECT virtuemart_media_id FROM #__virtuemart_product_medias WHERE virtuemart_media_id = m.virtuemart_media_id )
Просто уберите это условие. Оно вообще что даёт? Попробуйте без него и сравните результат.
Записан
Филипп Сорокин
Практически профи
*******

Репутация: +138/-4
Offline Offline

Пол: Мужской
Сообщений: 1807


« Ответ #18 : 11.07.2017, 19:13:10 »

А, всё, я понял, что Вы хотели. Вот, о чём говорили коллеги:

Код
SELECT 
 `file_title`,
 `file_url`,
 `published`,
 `virtuemart_media_id`
FROM #__virtuemart_medias AS m
LEFT JOIN #__virtuemart_product_medias AS pm USING(virtuemart_media_id)
WHERE m.file_type = 'product'
AND pm.virtuemart_media_id IS NULL
 
« Последнее редактирование: 11.07.2017, 19:16:58 от Филипп Сорокин » Записан
borro
Живу я здесь
******

Репутация: +21/-0
Offline Offline

Пол: Мужской
Сообщений: 1269


желаю вам счастья


« Ответ #19 : 12.07.2017, 14:50:27 »

А, всё, я понял, что Вы хотели. Вот, о чём говорили коллеги:
Добрый день! Написал я такой запрос. Судя по активности процесса mysqld в результатах команды top база данных отрабатывает предложенный вариант запроса примерно в течение 2,5 минут. Но раньше окончания её работы на экране всплывает 504 Gateway Time-out от nginx. Вывод - переходить к AJAX?
Записан
SeBun
Практически профи
*******

Репутация: +184/-5
Offline Offline

Пол: Мужской
Сообщений: 3158


@SeBun48


« Ответ #20 : 12.07.2017, 15:14:15 »

Вывод - переходить к AJAX?
Тут без вариантов. На большинстве хостингов таймаут по умолчанию равен 30 секундам. И оперировать такими объемами данных уже не получиться. Поэтому придется делать поэтапное решение задачи.
Записан
borro
Живу я здесь
******

Репутация: +21/-0
Offline Offline

Пол: Мужской
Сообщений: 1269


желаю вам счастья


« Ответ #21 : 12.07.2017, 16:36:29 »

Поэтому придется делать поэтапное решение задачи.
Если есть sql-запрос:
Код
SELECT 
 `file_title`,
 `file_url`,
 `published`,
 `virtuemart_media_id`
FROM #__virtuemart_medias AS m
LEFT JOIN #__virtuemart_product_medias AS pm USING(virtuemart_media_id)
WHERE m.file_type = 'product'
AND pm.virtuemart_media_id IS NULL
который сейчас за 2 минуты возвращает какой-то отображаемый результат, то как разбить выполняемую им задачу на куски, ставить LIMIT X,Y в конце запроса и каждый раз через AJAX передавать новые X,Y?
« Последнее редактирование: 12.07.2017, 17:13:42 от borro » Записан
SmokerMan
Профи
********

Репутация: +710/-26
Online Online

Пол: Мужской
Сообщений: 5366



« Ответ #22 : 12.07.2017, 17:14:54 »

который сейчас за 2 минуты возвращает какой-то отображаемый результат, то как разбить выполняемую им задачу на куски, ставить LIMIT X,Y в конце запроса и каждый раз через AJAX передавать новые X,Y?
не может этот запрос выполняться 2 минуты)
Записан
borro
Живу я здесь
******

Репутация: +21/-0
Offline Offline

Пол: Мужской
Сообщений: 1269


желаю вам счастья


« Ответ #23 : 12.07.2017, 17:21:00 »

не может этот запрос выполняться 2 минуты)
да, там все как-то и в правду неоднозначно. Если смотреть на ручные часы, он выполняется от 1 до 2,5 минут, если его выполнить в phpMyAdmin то с результатами возвращается надпись о том, что запрос выполнялся 8 секунд. Тем не менее по часам - все полторы минуты. Вот такая история...
Записан
SeBun
Практически профи
*******

Репутация: +184/-5
Offline Offline

Пол: Мужской
Сообщений: 3158


@SeBun48


« Ответ #24 : 12.07.2017, 17:25:53 »

Сделайте счетчик. Например так: в начале скрипта пишем
Код
$start = microtime(true);

Далее после выполнения какого то участка кода пишем
Код
echo 'Скрипт выполняется: '.(microtime(true) - $start).' сек.';

И станет понятно, какой участок у вас самый емкий. Но еще раз повторю то, что написали выше-юзайте JS и ставьте LIMIT в запросе.
Записан
Филипп Сорокин
Практически профи
*******

Репутация: +138/-4
Offline Offline

Пол: Мужской
Сообщений: 1807


« Ответ #25 : 12.07.2017, 17:44:39 »

Кажется, у Вас сервер, в принципе, умирает. Что-то с ним не так.

А если местами поменять:

Цитировать
WHERE m.file_type = 'product'
AND pm.virtuemart_media_id IS NULL

На

Код:
WHERE pm.virtuemart_media_id IS NULL
AND m.file_type = 'product'
Записан
borro
Живу я здесь
******

Репутация: +21/-0
Offline Offline

Пол: Мужской
Сообщений: 1269


желаю вам счастья


« Ответ #26 : 12.07.2017, 17:58:29 »

А если местами поменять:
Похоже чуть быстрее ответ. Например phpMyAdmin говорит, что 6 секунд вместо 8, но по часам ответ на экране был примерно через теже 1,5 минуты, может чуть быстрее. Получается что-то с настройками VPS? Что можно в этом случае там проверить и исправить?
Записан
Филипп Сорокин
Практически профи
*******

Репутация: +138/-4
Offline Offline

Пол: Мужской
Сообщений: 1807


« Ответ #27 : 12.07.2017, 18:05:48 »

Цитировать
Похоже чуть быстрее ответ.

А если так:

Код
SELECT 
 `file_title`,
 `file_url`,
 `published`,
 `virtuemart_media_id`
FROM #__virtuemart_medias AS m
LEFT JOIN #__virtuemart_product_medias AS pm USING(virtuemart_media_id)
WHERE pm.virtuemart_media_id IS NULL
HAVING m.file_type = 'product'

По логике должно обрабатываться одинаково, но всё же интересно.

Цитировать
Получается что-то с настройками VPS? Что можно в этом случае там проверить и исправить?

Оу, ну тут вообще искать иголку в стоге сена. Что используете, MariaDB или MySQL? Конфиг тогда в студию, что ли Azn
Записан
SmokerMan
Профи
********

Репутация: +710/-26
Online Online

Пол: Мужской
Сообщений: 5366



« Ответ #28 : 12.07.2017, 18:10:13 »

но по часам ответ на экране был примерно через теже 1,5 минуты, может чуть быстрее.
что значит ответ на экране?
если там выводиться вся эта простыня из запроса, то там сам браузер будет жутко тупить или вообще упасть, если там будет много записей в таблице
+ опять же там же наверное что-то делается до того как вывести на экран, не просто же этот запрос выполняется и все
Записан
SeBun
Практически профи
*******

Репутация: +184/-5
Offline Offline

Пол: Мужской
Сообщений: 3158


@SeBun48


« Ответ #29 : 12.07.2017, 18:11:55 »

Оу, ну тут вообще искать иголку в стоге сена...
Филипп, а зачем искать иголку, если время выполнения этого запроса зависит от объема записей в БД и аппаратных ресурсов сервера? Не проще реализовать то, что я предлагаю? Пусть немного дольше будет выполняться, зато правильно. И где гарантия, что потом хостер не начнет банить пользователей этого скрипта за превышение нагрузки? Да и ограничение по времени просто прервет его работу, если не успеет...
Записан
Страниц: [1] 2 3 4 5 6 7   Вверх
  Добавить закладку  |  Печать  
 
Перейти в:  

Powered by SMF 1.1.21 | SMF © 2006, Simple Machines

Joomlaforum.ru is not affiliated with or endorsed by the Joomla! Project or Open Source Matters.
The Joomla! name and logo is used under a limited license granted by Open Source Matters
the trademark holder in the United States and other countries.

LiveInternet