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

borro

  • Живу я здесь
  • 1281
  • 21
  • желаю вам счастья
Здравствуйте!

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

Если его вид 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

  • Профи
  • 4075
  • 376
Для запросов существует понятие LIMIT. А почему вид должен выполнять запросы в БД?
  • Не будь паразитом, сделай что-нибудь самостоятельно!
  • В личке и по Skype не даю советов.
*

Arkadiy

  • Группа развития
  • 5350
  • 440
  • Крепитесь, други.
Уберите подзапрос, сделайте либо отдельный запрос, либо внутреннее присоединение.
*

dmitry_stas

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

borro

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

borro

  • Живу я здесь
  • 1281
  • 21
  • желаю вам счастья
Уберите подзапрос, сделайте либо отдельный запрос, либо внутреннее присоединение.
вы про EXISTS() чтобы убрать?
*

borro

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

dmitry_stas

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

SeBun

  • Практически профи
  • 3143
  • 193
  • @SeBun48
А какая у вас задача стоит? Вы сделали запросы в цикле, как я понимаю, плюс не просто запрос, а с вложенным подзапросом. Посмотрите, сколько интераций выполняет цикл и посчитайте объем запросов в базу. И поймете, как делать нельзя. Возможно, перед циклом нужно сделать несколько запросов, взять значения и поместить в переменные, вместо того, что бы при каждой интерации делать запрос в базу. Опишите задачу, мы подскажем алгоритм.
Оказываю услуги по Joomla | Миграция на Joomla 3.x | Сопровождение | IT-аутсорсинг
*

borro

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

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

SeBun

  • Практически профи
  • 3143
  • 193
  • @SeBun48
У вас 30 секунд в большинстве случаев на выполнение. Еще один вопрос: кто запускает задачу, пользователь или крон?
Оказываю услуги по Joomla | Миграция на Joomla 3.x | Сопровождение | IT-аутсорсинг
*

borro

  • Живу я здесь
  • 1281
  • 21
  • желаю вам счастья
Еще один вопрос: кто запускает задачу, пользователь или крон?
пользователь из панели компонента в админке.
« Последнее редактирование: 11.07.2017, 15:06:59 от borro »
*

SeBun

  • Практически профи
  • 3143
  • 193
  • @SeBun48
пользователь их панели компонента в админке.

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

borro

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

robert

  • Профи
  • 4075
  • 376
1 запрос и 2 минуты?
- проиндексируйте поля привязки
- разбейте запрос на 2, как посоветовали выше, или используйте LEFT JOIN ...WHERE ...IS NULL
  • Не будь паразитом, сделай что-нибудь самостоятельно!
  • В личке и по Skype не даю советов.
*

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

  • Практически профи
  • 1816
  • 138
Код
AND NOT EXISTS(SELECT virtuemart_media_id FROM #__virtuemart_product_medias WHERE virtuemart_media_id = m.virtuemart_media_id )

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

  => мои публикации
    => мои работы
      => спектр моих услуг
*

borro

  • Живу я здесь
  • 1281
  • 21
  • желаю вам счастья
поля проиндексированы.
переделываю на вариант с left join, протестирую...
"разбейте запрос на 2" - не понял, это как?
*

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

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

  => мои публикации
    => мои работы
      => спектр моих услуг
*

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

  • Практически профи
  • 1816
  • 138
А, всё, я понял, что Вы хотели. Вот, о чём говорили коллеги:

Код: 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

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

SeBun

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

borro

  • Живу я здесь
  • 1281
  • 21
  • желаю вам счастья
Поэтому придется делать поэтапное решение задачи.
Если есть 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

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

borro

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

SeBun

  • Практически профи
  • 3143
  • 193
  • @SeBun48
Сделайте счетчик. Например так: в начале скрипта пишем
Код: php
$start = microtime(true);

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

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

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

  • Практически профи
  • 1816
  • 138
Кажется, у Вас сервер, в принципе, умирает. Что-то с ним не так.

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

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

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

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

  • Практически профи
  • 1816
  • 138
Цитировать
Похоже чуть быстрее ответ.

А если так:

Код: 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

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

SeBun

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