Новости Joomla

0 Пользователей и 1 Гость просматривают эту тему.
  • 217 Ответов
  • 7993 Просмотров
*

borro

  • Завсегдатай
  • 1379
  • 22 / 0
  • желаю вам счастья
Здравствуйте!

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

Если его вид 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, который вовсе не открывается :)
Наверно есть какие-то для это приёмы, ведь akeeba backup как-то работает, создавая архивы огромного сайта.
« Последнее редактирование: 10.07.2017, 15:59:44 от borro »
*

robert

  • Живу я здесь
  • 4974
  • 457 / 20
Для запросов существует понятие LIMIT. А почему вид должен выполнять запросы в БД?
Не будь паразитом, сделай что-нибудь самостоятельно!
*

Arkadiy

  • Гуру
  • 5317
  • 463 / 2
  • Крепитесь, други.
Уберите подзапрос, сделайте либо отдельный запрос, либо внутреннее присоединение.
*

dmitry_stas

  • Легенда
  • 13151
  • 1234 / 8
Наверно есть какие-то для это приёмы, ведь akeeba backup как-то работает, создавая архивы огромного сайта.
AJAX запросы. т.е. при каждом запросе выполняем какую-то маленькую часть работы, которая заведомо успевает выполнится, и возвращаем остаток сколько еще надо обработать. пока есть остаток - выводим прогрессбар, когда не остается - финальное сообщение.
Тут дарят бакс просто за регистрацию! Успей получить!
Все советы на форуме раздаю бесплатно, то есть даром. Индивидуально бесплатно консультирую только по вопросам стоимости индивидуальных консультаций
*

borro

  • Завсегдатай
  • 1379
  • 22 / 0
  • желаю вам счастья
Доброе утро. Спасибо за отклик.
Для запросов существует понятие LIMIT. А почему вид должен выполнять запросы в БД?
А как просчитать, сколько ставить в LIMIT, чтобы сервер не поперхнулся и не ленился одновременно? :) Я наверно неправильно выразился про вид, модель обращается и дает данные виду
« Последнее редактирование: 11.07.2017, 09:23:08 от borro »
*

borro

  • Завсегдатай
  • 1379
  • 22 / 0
  • желаю вам счастья
Уберите подзапрос, сделайте либо отдельный запрос, либо внутреннее присоединение.
вы про EXISTS() чтобы убрать?
*

borro

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

dmitry_stas

  • Легенда
  • 13151
  • 1234 / 8
ну вы же сами упомянули про Akeeba Backup. она и есть пример, ее и разбирайте, там все есть.
Тут дарят бакс просто за регистрацию! Успей получить!
Все советы на форуме раздаю бесплатно, то есть даром. Индивидуально бесплатно консультирую только по вопросам стоимости индивидуальных консультаций
*

SeBun

  • BanMaster
  • 4018
  • 259 / 5
  • @SeBun48
А какая у вас задача стоит? Вы сделали запросы в цикле, как я понимаю, плюс не просто запрос, а с вложенным подзапросом. Посмотрите, сколько интераций выполняет цикл и посчитайте объем запросов в базу. И поймете, как делать нельзя. Возможно, перед циклом нужно сделать несколько запросов, взять значения и поместить в переменные, вместо того, что бы при каждой интерации делать запрос в базу. Опишите задачу, мы подскажем алгоритм.
Оказываю услуги по Joomla | Миграция/Обновление | Сопровождение | IT-аутсорсинг | Недорогие домены и хостинг
*

borro

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

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

SeBun

  • BanMaster
  • 4018
  • 259 / 5
  • @SeBun48
У вас 30 секунд в большинстве случаев на выполнение. Еще один вопрос: кто запускает задачу, пользователь или крон?
Оказываю услуги по Joomla | Миграция/Обновление | Сопровождение | IT-аутсорсинг | Недорогие домены и хостинг
*

borro

  • Завсегдатай
  • 1379
  • 22 / 0
  • желаю вам счастья
Еще один вопрос: кто запускает задачу, пользователь или крон?
пользователь из панели компонента в админке.
« Последнее редактирование: 11.07.2017, 15:06:59 от borro »
*

SeBun

  • BanMaster
  • 4018
  • 259 / 5
  • @SeBun48
пользователь их панели компонента в админке.

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

borro

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

robert

  • Живу я здесь
  • 4974
  • 457 / 20
1 запрос и 2 минуты?
- проиндексируйте поля привязки
- разбейте запрос на 2, как посоветовали выше, или используйте LEFT JOIN ...WHERE ...IS NULL
Не будь паразитом, сделай что-нибудь самостоятельно!
*

Филипп Сорокин

  • Завсегдатай
  • 1918
  • 160 / 4
  • разработчик.москва
Код
AND NOT EXISTS(SELECT virtuemart_media_id FROM #__virtuemart_product_medias WHERE virtuemart_media_id = m.virtuemart_media_id )

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

borro

  • Завсегдатай
  • 1379
  • 22 / 0
  • желаю вам счастья
поля проиндексированы.
переделываю на вариант с left join, протестирую...
"разбейте запрос на 2" - не понял, это как?
*

Филипп Сорокин

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

Филипп Сорокин

  • Завсегдатай
  • 1918
  • 160 / 4
  • разработчик.москва
А, всё, я понял, что Вы хотели. Вот, о чём говорили коллеги:

Код: 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
« Последнее редактирование: 11.07.2017, 18:16:58 от Филипп Сорокин »
*

borro

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

SeBun

  • BanMaster
  • 4018
  • 259 / 5
  • @SeBun48
Вывод - переходить к AJAX?
Тут без вариантов. На большинстве хостингов таймаут по умолчанию равен 30 секундам. И оперировать такими объемами данных уже не получиться. Поэтому придется делать поэтапное решение задачи.
Оказываю услуги по Joomla | Миграция/Обновление | Сопровождение | IT-аутсорсинг | Недорогие домены и хостинг
*

borro

  • Завсегдатай
  • 1379
  • 22 / 0
  • желаю вам счастья
Поэтому придется делать поэтапное решение задачи.
Если есть sql-запрос:
Код: 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, 16:13:42 от borro »
*

SmokerMan

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

borro

  • Завсегдатай
  • 1379
  • 22 / 0
  • желаю вам счастья
не может этот запрос выполняться 2 минуты)
да, там все как-то и в правду неоднозначно. Если смотреть на ручные часы, он выполняется от 1 до 2,5 минут, если его выполнить в phpMyAdmin то с результатами возвращается надпись о том, что запрос выполнялся 8 секунд. Тем не менее по часам - все полторы минуты. Вот такая история...
*

SeBun

  • BanMaster
  • 4018
  • 259 / 5
  • @SeBun48
Сделайте счетчик. Например так: в начале скрипта пишем
Код: php
$start = microtime(true);

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

И станет понятно, какой участок у вас самый емкий. Но еще раз повторю то, что написали выше-юзайте JS и ставьте LIMIT в запросе.
Оказываю услуги по Joomla | Миграция/Обновление | Сопровождение | IT-аутсорсинг | Недорогие домены и хостинг
*

Филипп Сорокин

  • Завсегдатай
  • 1918
  • 160 / 4
  • разработчик.москва
Кажется, у Вас сервер, в принципе, умирает. Что-то с ним не так.

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

Цитировать
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

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

Филипп Сорокин

  • Завсегдатай
  • 1918
  • 160 / 4
  • разработчик.москва
Цитировать
Похоже чуть быстрее ответ.

А если так:

Код: 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 pm.virtuemart_media_id IS NULL
HAVING m.file_type = 'product'

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

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

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

SmokerMan

  • Гуру
  • 5293
  • 720 / 26
но по часам ответ на экране был примерно через теже 1,5 минуты, может чуть быстрее.
что значит ответ на экране?
если там выводиться вся эта простыня из запроса, то там сам браузер будет жутко тупить или вообще упасть, если там будет много записей в таблице
+ опять же там же наверное что-то делается до того как вывести на экран, не просто же этот запрос выполняется и все
*

SeBun

  • BanMaster
  • 4018
  • 259 / 5
  • @SeBun48
Оу, ну тут вообще искать иголку в стоге сена...
Филипп, а зачем искать иголку, если время выполнения этого запроса зависит от объема записей в БД и аппаратных ресурсов сервера? Не проще реализовать то, что я предлагаю? Пусть немного дольше будет выполняться, зато правильно. И где гарантия, что потом хостер не начнет банить пользователей этого скрипта за превышение нагрузки? Да и ограничение по времени просто прервет его работу, если не успеет...
Оказываю услуги по Joomla | Миграция/Обновление | Сопровождение | IT-аутсорсинг | Недорогие домены и хостинг
Чтобы оставить сообщение,
Вам необходимо Войти или Зарегистрироваться