Автор Тема: Медленный запрос в модуле blocklayered  (Прочитано 459 раз)

06 Май 2015, 12:02:04
  • Старожил
  • ****
  • Сообщений: 300
  • Репутация: +1/-0
  • Сообщество PrestaShop
    • Просмотр профиля
Медленный запрос в модуле blocklayered
Значит установил define('_PS_DEBUG_PROFILING_', true);
с целью узнать самый медленный запрос и вот что мне выдало

Время выполнение данного запроса 12,9 секунд.

Вот сам запрос
SELECT SQL_NO_CACHE p.*,
product_shop.*,
product_shop.id_category_default,
pl.*,
MAX(image_shop.`id_image`) id_image,
il.legend,
m.name manufacturer_name,
MAX(product_attribute_shop.id_product_attribute) id_product_attribute,
DATEDIFF(product_shop.`date_add`, DATE_SUB(NOW(), INTERVAL 100 DAY)) > 0 AS new,
stock.out_of_stock, IFNULL(stock.quantity, 0) as quantity
FROM `ps_category_product` cp
LEFT JOIN ps_category c ON (c.id_category = cp.id_category)
LEFT JOIN `ps_product` p ON p.`id_product` = cp.`id_product`
INNER JOIN ps_product_shop product_shop
ON (product_shop.id_product = p.id_product AND product_shop.id_shop = 1)
LEFT JOIN `ps_product_attribute` pa ON (p.`id_product` = pa.`id_product`)
LEFT JOIN ps_product_attribute_shop product_attribute_shop
ON (product_attribute_shop.id_product_attribute = pa.id_product_attribute AND product_attribute_shop.id_shop = 1 AND product_attribute_shop.`default_on` = 1)
LEFT
JOIN ps_stock_available stock
ON (stock.id_product = p.id_product AND stock.id_product_attribute = IFNULL(`product_attribute_shop`.id_product_attribute, 0) AND stock.id_shop = 1  AND stock.id_shop_group = 0  )
LEFT JOIN ps_product_lang pl ON (pl.id_product = p.id_product AND pl.id_shop = 1  AND pl.id_lang = 1)
LEFT JOIN `ps_image` i  ON (i.`id_product` = p.`id_product`) LEFT JOIN ps_image_shop image_shop
ON (image_shop.id_image = i.id_image AND image_shop.id_shop = 1 AND image_shop.cover=1)
LEFT JOIN `ps_image_lang` il ON (image_shop.`id_image` = il.`id_image` AND il.`id_lang` = 1)
LEFT JOIN ps_manufacturer m ON (m.id_manufacturer = p.id_manufacturer)
WHERE product_shop.`active` = 1 AND product_shop.`visibility` IN ("both", "catalog")
AND c.nleft >= 37 AND c.nright <= 80
AND c.active = 1
AND p.id_product IN (217,221,222,223,224,225,226,228,233,234,236,239,240,242,243,244,245,247,248,250,253,262,263,273,288,296,297,298,299,300,321,322,323,324,325,326,327,329,330,331,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,350,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,556,557,558,559,560,561,562,563,566,582,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,646,647,648,649,651,656,657,658,659,664,665,666,667,676,677,678,679,684,685,686,687,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,962,963,964,965,966,967,968,969,970,971,972,973,974,975,976,977,978,979,980,981,982,983,984,985,986,987,988,989,990,991,992,993,994,999,1000,1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1011,1012,1013,1014,1015,1016,1017,1018,1019,1020,1021,1022,1023,1024,1025,1026,1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,1037,1038,1039,1040,1041,1042,1043,1044,1045,1046)
GROUP BY product_shop.id_product
ORDER BY cp.position desc LIMIT 0,12

И ещё почему указано в запросе  SQL_NO_CACHE (почему данные не берутся из кеша), хотя в самом модуле blocklayered этого нет, там сразу идёт

$this->products = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('
SELECT
p.*,
'.($alias_where == 'p' ? '' : 'product_shop.*,' ).'
'.$alias_where.'.id_category_default, и т.д.


Заранее спасибо!
06 Май 2015, 13:16:49
Ответ #1
  • Ветеран
  • *****
  • Сообщений: 852
  • Репутация: +7/-0
  • Сообщество PrestaShop
    • Просмотр профиля
blocklayered самый тормозной модуль. Его бы полностью переделать.
06 Май 2015, 14:11:42
Ответ #2
  • Старожил
  • ****
  • Сообщений: 300
  • Репутация: +1/-0
  • Сообщество PrestaShop
    • Просмотр профиля
blocklayered самый тормозной модуль. Его бы полностью переделать.

Хорошо, а почему не кешируется запрос?
06 Май 2015, 14:35:22
Ответ #3
  • Ветеран
  • *****
  • Сообщений: 1288
  • Репутация: +34/-1
  • Сообщество PrestaShop
    • Просмотр профиля
Этот модуль не кеширует запросы к серверу mysql.
06 Май 2015, 14:47:39
Ответ #4
  • Ветеран
  • *****
  • Сообщений: 20938
  • Репутация: +25280/-0
  • Prestashop - просто и эффективно
    • Просмотр профиля
Сервер настроен? Версия MySQL какая? Кеш запросов доступен в MySQL начиная с версии 4.0.
Эксперт Prestashop - решения всех проблем, написание модулей, создание тем для интернет-магазинов под Prestashop.
Эксперт Magento - создам сайт на Magento, программирование кастомных модулей для Magento, кастомизация тем Magento.
Лучшие цены!!!
06 Май 2015, 15:57:00
Ответ #5
  • Старожил
  • ****
  • Сообщений: 300
  • Репутация: +1/-0
  • Сообщество PrestaShop
    • Просмотр профиля
Сервер настроен? Версия MySQL какая? Кеш запросов доступен в MySQL начиная с версии 4.0.

MySQL не кеширует запросы, результаты которых могут измениться. Например, запросы в которых используются функции, относящиеся к текущему времени NOW().

Так вот убрал из запроса такую строку
DATEDIFF('.$alias_where.'.`date_add`, DATE_SUB(NOW(), INTERVAL '.(int)$nb_day_new_product.' DAY)) > 0 AS new,
Функционал остался прежним, на что вообще влияет эта строка?
06 Май 2015, 16:51:20
Ответ #6
  • Ветеран
  • *****
  • Сообщений: 33044
  • Репутация: +26761/-0
    • Просмотр профиля
Разница дат даст статус товару - Новый / не новый.
06 Май 2015, 17:02:29
Ответ #7
  • Ветеран
  • *****
  • Сообщений: 13832
  • Репутация: +14564/-2
  • Сообщество PrestaShop
    • Просмотр профиля
Так вот убрал из запроса такую строку
DATEDIFF('.$alias_where.'.`date_add`, DATE_SUB(NOW(), INTERVAL '.(int)$nb_day_new_product.' DAY)) > 0 AS new,
Функционал остался прежним, на что вообще влияет эта строка?
Не сможете использовать фильтр "Показать только новые товары". Если он не нужен, то можно удалять.
07 Май 2015, 10:22:45
Ответ #8
  • Старожил
  • ****
  • Сообщений: 300
  • Репутация: +1/-0
  • Сообщество PrestaShop
    • Просмотр профиля
Раз пошло такое дело.
Как можно ещё упростить данный запрос, повысив при этом его быстродействие?
Что можно ещё убрать?
07 Май 2015, 10:50:20
Ответ #9
  • Ветеран
  • *****
  • Сообщений: 13832
  • Репутация: +14564/-2
  • Сообщество PrestaShop
    • Просмотр профиля
Сами понимаете, что модуль сделан "на все возможные варианты". Упрощать нужно под своии требования. Если у вас фитьтр только категории и товару, то оставить в запросе выборку этих данных, только select без всяких функций, тогда будет кешировать и т.д.
07 Май 2015, 10:57:52
Ответ #10
  • Старожил
  • ****
  • Сообщений: 300
  • Репутация: +1/-0
  • Сообщество PrestaShop
    • Просмотр профиля
Сами понимаете, что модуль сделан "на все возможные варианты". Упрощать нужно под своии требования. Если у вас фитьтр только категории и товару, то оставить в запросе выборку этих данных, только select без всяких функций, тогда будет кешировать и т.д.
Спасибо за ответ.
Не могли бы показать вариант такого запроса, чтобы он кешировался.
Заранее большое спасибо!
07 Май 2015, 11:12:09
Ответ #11
  • Ветеран
  • *****
  • Сообщений: 13832
  • Репутация: +14564/-2
  • Сообщество PrestaShop
    • Просмотр профиля
В базовых функциях класса DB в prestashop есть примеры
/**
 * Execute a query
 *
 * @param string $sql
 * @param bool $use_cache
 * @return bool
 */
public function execute($sql, $use_cache = true)
кеширование включено по дефолту. Нужно только чтобы серверное по было настроено для кешировани.
07 Май 2015, 11:19:35
Ответ #12
  • Ветеран
  • *****
  • Сообщений: 20938
  • Репутация: +25280/-0
  • Prestashop - просто и эффективно
    • Просмотр профиля
Сервер настроен? Версия MySQL какая? Кеш запросов доступен в MySQL начиная с версии 4.0.
MySQL не кеширует запросы, результаты которых могут измениться. Например, запросы в которых используются функции, относящиеся к текущему времени NOW().
Так вот убрал из запроса такую строку
DATEDIFF('.$alias_where.'.`date_add`, DATE_SUB(NOW(), INTERVAL '.(int)$nb_day_new_product.' DAY)) > 0 AS new,
Функционал остался прежним, на что вообще влияет эта строка?
Начинать нужно с версии MySQL. Если она у вас меньше 4, то какая вам разница, что в запросе есть функция? Все равно запрос не будет кешироваться.
Удалять такие строки не обязательно, можно просто заменить функции текущего времени (NOW(), CURDATE() и др.) на строку с датой.
Эксперт Prestashop - решения всех проблем, написание модулей, создание тем для интернет-магазинов под Prestashop.
Эксперт Magento - создам сайт на Magento, программирование кастомных модулей для Magento, кастомизация тем Magento.
Лучшие цены!!!
07 Май 2015, 11:51:07
Ответ #13
  • Старожил
  • ****
  • Сообщений: 300
  • Репутация: +1/-0
  • Сообщество PrestaShop
    • Просмотр профиля
Версия сервера: 5.1.73-log - Source distribution
С этим всё в порядке.
08 Май 2015, 10:23:55
Ответ #14
  • Старожил
  • ****
  • Сообщений: 300
  • Репутация: +1/-0
  • Сообщество PrestaShop
    • Просмотр профиля
Подскажите, правильно ли я думаю, что при
define('_PS_DEBUG_PROFILING_', true);Во все запросы с SELECT автоматически подставляется SQL_NO_CACHE
с целью тестирования этих самых запросов по времени выполнения?