Здравствуй, уважаемый друг!

Кажется, ты используешь AdBlock. Этот проект развивается и существует за счет доходов от рекламы.
Добавь, пожалуйста, нас в исключения.

Спасибо за понимание.

Создание сайтов Харьков

Как не положить БД MySQL, используя поиск по атрибутам в WebAsyst ShopScript

28 февраля 2013 в 17:47 Автор: Nikita_Sp в категории Статьи о php 2 комментария

Добрый день, уважаемые читатели моего блога!

Данная статья является продолжением истории с WA SS, начало которой вы можете прочитать тут: WebAsyst наплевать на владельцев ShopScript или как положить БД владельца интернет-магазина ShopScript.

По многочисленным просьбам на форуме WebAsyst’a я пишу эту запись. Ничего сложного или необычного в данной статье нет, но тем не менее, благодаря этому  хаку вы можете избежать «уложения» вашей БД MySQL.

Итак, приступим. Открываем файл:
C:\WebServers\home\domain\www\published\SC\html\scripts\core_functions\product_functions.php

В данном файле находим функцию _prepareSearchExtraParameters.
Немного о функции: данная функция составляет запрос в базу данных на основании тех параметров которые ей переданы (атрибуты, категории и т.п.).

На 507 строке мы видим открытие цикла, который прогоняет все item’ы и на 517 мы видим что каждый раз в массив $sqls_joins добавляется новый LEFT JOIN, который собственно и грузит нашу базу. Для примера могу сказать, что при тесте  на локальном сервере запрос, имеющий 1x LEFT JOIN занял 0,002 сек., в то время как 2xLEFT JOIN заняло 8,8 секунд. (возможна погрешность в данных, ибо пишу спустя неделю после теста :), могу сказать одно, что разница между временем была в 500 раз).

На каждом проходе нашего цикла присоединяется ОДНА И ТАКЖЕ ТАБЛИЦА с разным именем, которое просто инкрементируется!

LEFT JOIN SC_product_options_values PrdOptVal0 ON p.productID=PrdOptVal0.`productID`
 LEFT JOIN SC_product_options_set PrdOptSet0 ON p.productID=PrdOptSet0.`productID`

LEFT JOIN SC_product_options_values PrdOptVal1 ON p.productID=PrdOptVal1.`productID`
 LEFT JOIN SC_product_options_set PrdOptSet1 ON p.productID=PrdOptSet1.`productID`

Это происходит на 519 строке:

			$sqls_joins[] = '
				LEFT JOIN ?#PRODUCT_OPTIONS_VALUES_TABLE PrdOptVal'.$cnt.' ON p.productID=PrdOptVal'.$cnt.'.productID
				LEFT JOIN ?#PRODUCTS_OPTIONS_SET_TABLE PrdOptSet'.$cnt.' ON p.productID=PrdOptSet'.$cnt.'.productID
				LEFT JOIN ?#PRODUCTS_OPTIONS_VALUES_VARIANTS_TABLE PrdOptValVar'.$cnt.' ON
					PrdOptSet'.$cnt.'.optionID=PrdOptValVar'.$cnt.'.optionID AND
					PrdOptSet'.$cnt.'.variantID=PrdOptValVar'.$cnt.'.variantID
			';

На 543 строке:

			$sqls_joins[] = '
				LEFT JOIN ?#PRODUCT_OPTIONS_VALUES_TABLE PrdOptVal'.$cnt.' ON p.productID=PrdOptVal'.$cnt.'.`productID`
				LEFT JOIN ?#PRODUCTS_OPTIONS_SET_TABLE PrdOptSet'.$cnt.' ON p.productID=PrdOptSet'.$cnt.'.`productID`
			';

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

Для того чтобы избежать такого казуса, я внес банальные и возможно, не совсем красивые, с точки зрения правил хорошего тона в программировании, изменения.
Необходимо просто убрать все упоминания о переменной $cnt и изменить строки 519 и 543 таким образом, чтобы не создавался, а перезаписывался элемент массива. Таким образом мы уберем лишние объединения таблиц в запросе.

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

Если у вас возникнут вопросы или предложения по улучшению данного мануала — пишите мне в комментарии/вопросы-ответы — буду рад ответить или принять к сведению ваши предложения!

Удачной оптимизации кода! 🙂

2 комментария

Добавить комментарий для Nikita_Sp Отменить ответ

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Вверх!

Меню блога

Категории блога

Облако тегов