Тормоза при редактировании товара
#1
Отправлено 17 June 2013 - 10:04 PM
штатный
UPDATE .PRODUCTS_TABLE. SET a=b.....WHERE productID=(int)$productID
в функции ProductUpdate (как-то так) или сначала
DELETE .PRODUCTS_TABLE. WHERE productID=(int)$productID
затем
INSERT .PRODUCTS_TABLE. SET a=b.....WHERE productID=(int)$productID
?
Сергей и так в курсе странной проблемы, а остальным вкратце опишу - при базе ShopCMS с ОЧЕНЬ большим (~1500) количеством категорий наблюдается странная тормознутость при сохранении отредактированного товара, 10-20секунд. Хотя там банально одна функция с одним SQL-запросом, которая и сохраняет (апдейтит) все значения за один запрос. И не видится НИКАКОЙ связи с таблицей категорий, т.е. совершенно не важно, сколько их там - десять или полторы тысячи.
PS. А что будет и может ли возникать тормознуть просто при частом изменений свойств товара? Т.е. примерно как в стареньких DBF-табличках, где записи помечались как "удаленные", т.е. пока не применялась специальная процедура сжатия - таблица росла и все более тормозила. Как по этой части у SQL-таблиц? нет ли каких процедур "сжатия"?
Глядя совсем уж в корень - ЧТО ДЕЛАЕТ процедура "Для оптимизации базы нажмите тут" в "Администрирование БД"? Понятно, что могу сам посмотреть, но мало ли кто уже разбирал и в двух словах объяснит?
#2
Отправлено 17 June 2013 - 10:06 PM
#3
Отправлено 17 June 2013 - 10:22 PM
Не совсем так. Я высказал предположение, что если раньше проблемы не было (или она была не настолько заметна), но она проявилась после смены хостинга, хотя ничего по коду не менялось... Дальше логика, как мне кажется, понятна и вполне справедлива .Так это ты тот самый подрядчик который грешит на мой хостинг
Я таки думаю, что проблема с SQL-таблицей товаров, которая часто редактируется по ценам (как мне подозревается довольно уверенно). Т.е. корень надо искать именно тут. Толи таблица товаров просто разрастается, толи делается менее оптимальной и тормозной (ключи?), но чудес не бывает и либо я чего-то не замечаю в простейшей процедуре, либо надо как-то оптимизировать (сжать? почистить? отсортировать? ) эту таблицу.
PS. Ну и несложно догадаться, что я понятия не имел о принадлежности хостинга. Не дошел я еще до уровня определения принадлежности и хорошести хостинга по IP-адресу .
PPS. В общем, тут нужен совет кого-то, кто на порядок лучше меня разбирается в принципах устройства SQL-хранилища.
#4
Отправлено 17 June 2013 - 10:28 PM
Думаю ты ошибаешься.Толи таблица товаров просто разрастается, толи делается менее оптимальной и тормозной (ключи?),
Я сделал копию полную сайта и переместил все товары в одну категорию, остальные категории удалил.
Все стало работать мгновенно, т.е. в таблице товаров ничего не изменилось, кроме айдишника в поле категории.
Нужно искать связь с таблицей категорий.... если она так влияет значит есть связь есть, просто видимо не так очевидна.
А на счет того что быстрее обновление запили или удаление и добавление, ИМХО логично что второй вариант дольше т.к. в первом 1 запрос а во втором 2, при этом второй (добавление) по структуре собственно практически повторяет обновление.
#5
Отправлено 19 June 2013 - 01:25 PM
Тьфу ты, блин... А с чего, собственно, мной решилось, что тормоза происходят именно при сохранении товара?Т.е. надо лезть в admin.php и разбирать более четко
Ведь после сохранения товара происходит перезагрузка страницы со списком товаров и категориями, где, как я подозреваю, и происходят те самые тормоза в силу полутора тысяч категорий, вот!
#6
Отправлено 19 June 2013 - 02:27 PM
#7
Отправлено 19 June 2013 - 04:24 PM
#8
Отправлено 19 June 2013 - 07:36 PM
Заключается она в следующем
При редактировании товара, а точнее при сохранении выполняется функция
update_psCount(1)
при том почему-то дважды
первый раз ее вызов в
function UpdateProduct
а второй раз ее вызов в admin.php после добавления или редактирования товара
if (CONF_UPDATE_GCV == '1') update_psCount(1);
Вот она то и вызывает этот ступор, т.к. идет пересчет кол-ва категорий и товаров в каждой категории.
После того как я закомментировал их сохраняться стало за пару секунд.
Гораздо правильнее конечно было бы добавить условие чтобы данная функция вызывалась только в случае изменения категории, а не каждый раз.
#9
Отправлено 19 June 2013 - 07:54 PM
Там в функции UpdateProduct последний параметр как раз запрещает-разрешает запуск пересчета. Это кроме установки в "Общих настройках" CONF_UPDATE_GCV. Но он нигде не используется, т.е. всегда =1 и не влияет. ИМХО, в данном случае (на этом сайте) решением будет просто выключить в "Общих настройках" галку "Показывать количество товаров в категориях", т.к. в используемом шаблоне это количество один хрен не показывается .
PS. Хм... А оно там выключено. Т.е. функция update_psCount не должна вызываться. Или это ты уже выключил?
#10
Отправлено 19 June 2013 - 07:59 PM
А вот на счет показывать/не показывать я как-то не уверен что эта галка имеет смысл.
Дело в том что кол-во товаров в категории и кол-во подкатегорий используется не только в отображении, а и в менюшках насколько я помню, а может и еще где..... всего не помню.
#11
Отправлено 19 June 2013 - 08:27 PM
Хмм... CONF_UPDATE_GCV вообще имеет settings_groupID=1, т.е. не меняется штатно в настройках.Нет я не выключал я закомментировал вызов этой функции.
Ну, тогда вставить в select выбора категории в настройках товара onchahge="$('input[/'#category_changed/']').value=1" и добавить <input type="hidden" id="category_changed" name="category_changed" value="0"> и выполнять функцию update_psCount по условию if($_POST["category_changed"] == 1)
Я бы сделал как-то так.
PS. Надо таки сделать что-то типа "Расширенные настройки". А то там куча настроек с settings_groupID=1, с названиями и описаниями, но даже не посмотреть, что это и на что влияет .
#12
Отправлено 19 June 2013 - 08:30 PM
#13
Отправлено 19 June 2013 - 08:34 PM
Да, так заметно изящнее будет.сравнивал бы значение ID категории текущей с ID которое передается в пост
#14
Отправлено 12 August 2013 - 02:25 AM
Я решил немного по другому, попроще в реализации. Функция вызывается как и раньше (по поводу и без повода), это я копать не стал, а просто минимизировал количество запросов. Штатно там на каждую категорию идет восемь (!) SQL-запросов. Рекурсивно, обходя все дерево категорий. Т.е. при 1000 категорий получим 8тыс запросов при сохранении товара. Точнее, даже 16тыс (см. про вызов функции два раза).Такс ну что, нашел я проблему. Заключается она в следующем При редактировании товара, а точнее при сохранении выполняется функция update_psCount(1) при том почему-то дважды первый раз ее вызов в function UpdateProduct а второй раз ее вызов в admin.php после добавления или редактирования товара if (CONF_UPDATE_GCV == '1') update_psCount(1); Вот она то и вызывает этот ступор, т.к. идет пересчет кол-ва категорий и товаров в каждой категории. После того как я закомментировал их сохраняться стало за пару секунд. Гораздо правильнее конечно было бы добавить условие чтобы данная функция вызывалась только в случае изменения категории, а не каждый раз.
Прилагаемый ниже код для пересчета любого количества категорий выполняет четыре запроса, если это не первый пересчет в жизни сайта. На сайте с 1500 категорий ускорение действительно очень заметно.
Установка:
В файле category_functions.php
1. в функции update_psCount
строку
update_pCount($parent);
заменяем на
update_pCount_new($parent);
2. куда-нибудь рядом добавляем две функции
function update_sCount_new($parent, $counts = array(1 => array ('subcats' => 0,'admin_count' => 0,'customer_count' => 0)))
{
global $mc;
foreach (array_keys ($mc,(int)$parent) as $val)
{
$counts[$val]['subcats'] = count(array_keys($mc, $val));
$counts[$val]['admin_count'] = 0;
$counts[$val]['customer_count'] = 0;
if ($counts[$val]['subcats']) $counts = update_sCount_new($val,$counts);
}
return $counts;
}
function update_pCount_new($parent)
{
global $fc;
$qstr = array(
"SELECT categoryID, COUNT(*) AS admcount, COUNT(NULLIF(enabled,0)) AS count FROM ".PRODUCTS_TABLE." GROUP BY categoryID",
"SELECT pc.categoryID, count(*) AS admcount, COUNT(NULLIF(enabled,0)) AS count FROM ".CATEGORIY_PRODUCT_TABLE." AS pc JOIN ".PRODUCTS_TABLE." USING (productID) GROUP BY pc.categoryID");
$counts = update_sCount_new($parent);
foreach ($qstr as $str)
{
$data = db_query($str);
while ($row=db_fetch_assoc($data))
{
$categoryID = (int)$row['categoryID'];
while ($categoryID)
{
$counts[$categoryID]['admin_count'] += (int)$row['admcount'];
$counts[$categoryID]['customer_count'] += (int)$row['count'];
$categoryID = $fc[$categoryID]['parent'];
}
}
}
$data = db_query("SELECT categoryID, subcount, products_count, products_count_admin FROM ".CATEGORIES_TABLE);
while ($row = db_fetch_assoc($data))
{
$categoryID = (int)$row['categoryID'];
if ((int)$row['subcount'] != $counts[$categoryID]['subcats'] || (int)$row['products_count'] != $counts[$categoryID]['customer_count'] || (int)$row['products_count_admin'] != $counts[$categoryID]['admin_count'])
db_query("UPDATE ".CATEGORIES_TABLE." SET subcount=".$counts[$categoryID]['subcats'].", products_count=".$counts[$categoryID]['customer_count'].", products_count_admin=".$counts[$categoryID]['admin_count']." WHERE categoryID=$categoryID");
}
}
#15
Отправлено 19 August 2013 - 12:59 PM
#16
Отправлено 19 August 2013 - 02:20 PM
Не очень понимаю связь между расширенным поиском (который в клиентской части) и скоростью сохранения товаров в админке.вот в ветке про расширенный поиск я эту проблему и пытался описать.
#17
Отправлено 19 August 2013 - 02:25 PM
#18
Отправлено 18 April 2014 - 09:32 PM
Надо заменить
function update_sCount_new($parent, $counts = array())
на
function update_sCount_new($parent, $counts = array(1 => array ('subcats' => 0,'admin_count' => 0,'customer_count' => 0)))
в исходнике уже исправлено.
#19
Отправлено 08 May 2014 - 05:43 PM
Пересчет товаров при каждом сохранении можно отключить, но ответственный за это параметр скрыт в базе данных. Включить отображение параметра можно с помощью следующего SQL запроса:
UPDATE ваш_префикс_settings SET settings_groupID=2 WHERE settings_constant_name='CONF_UPDATE_GCV' LIMIT 1
После в общих настройках появится Автоматически обновлять количество товаров в категориях (в администрации)