Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/topic.php on line 737
Форумы портала PHP.SU :: Оптимизация категоризированного поиска товаров.

 PHP.SU

Программирование на PHP, MySQL и другие веб-технологии
PHP.SU Портал     На главную страницу форума Главная     Помощь Помощь     Поиск Поиск     Поиск Яндекс Поиск Яндекс     Вакансии  Пользователи Пользователи


 Страниц (2): [1] 2 »   

> Без описания
Sheehave
Отправлено: 13 Мая, 2015 - 15:54:04
Post Id


Новичок


Покинул форум
Сообщений всего: 7
Дата рег-ции: Май 2015  


Помог: 0 раз(а)




Добрый день.

Столкнулся с проблемой скорости загрузки страниц на каталогах подарков http://begift[dot]ru/ и http://begift[dot]com[dot]ua/ На сайте каждый товар имеет ряд параметров, которые его характеризуют. Параметры, в свою очередь, разбиты по категориям. Например, товар: цветы имеют параметры «Праздник» – 8 Марта, 14 Февраля… и «Кому подарить»: Маме, Жене, Девушке и т.д. Пользователь может свободно комбинировать параметры, на основе которых ему показываются подходящие товары. Пытаюсь оптимизировать данную страницу, поскольку время генерации составляет неприличные 10-15 сек: http://tools[dot]pingdom[dot]com/fpt/#!/[dot][dot][dot]god-iz-igrushek/

Подбор товара осуществляется алгоритмом: параметры внутри категории объединяются оператором ИЛИ, сами категории – оператором И. Страница, кроме основного списка, показывает также количество подарков, которое будет получено путем комбинирования уже выбранных и дополнительных параметров. Этот расчет также происходит по тому же алгоритму. Таким образом, мы имеем около 30 таких выборок на каждую загрузку страницы. В большинстве случаев используем подготовленные запросы, но для таких страниц запрос полностью генерируется в php коде вместе с параметрами. Он довольно объемный и плохо оптимизируется с самой базой. Я уже реализовал кэширование (сохраняя результаты всех вычислений для каждой страницы) на стороне сервера. Так как стоимость товара и его наличие обновляется, то этот кэш нужно обновлять раз в 1-2 дня. Страниц около 3000, если кэшировать каждую каждый день, то только на кэширование уйдет 10 часов.

Хочу провести сравнительные тесты разных альтернативных алгоритмов. Возможно, у кого-то есть опыт в таких задачах. Буду благодарен за совет.
 
 Top
Мелкий Супермодератор
Отправлено: 13 Мая, 2015 - 16:02:35
Post Id



Активный участник


Покинул форум
Сообщений всего: 11926
Дата рег-ции: Июль 2009  
Откуда: Россия, Санкт-Петербург


Помог: 618 раз(а)




Sheehave пишет:
Таким образом, мы имеем около 30 таких выборок на каждую загрузку страницы.

Из чего это вытекает?

Покажите схему БД и код. Если цифры на главной имеют отношение к количеству предложений - то городить несколько уровней кэшей ради пустяковых пары тысяч товаров смешно.


-----
PostgreSQL DBA
 
 Top
DeepVarvar Супермодератор
Отправлено: 13 Мая, 2015 - 16:09:58
Post Id



Активный участник


Покинул форум
Сообщений всего: 10377
Дата рег-ции: Дек. 2008  
Откуда: Альфа Центавра


Помог: 353 раз(а)




Мало инфы. Ты там что, лайками ищешь чтоли? Для каждого параметра заведи айдишник. Ищи по названию в таблице параметров и джойнь все товары через таблицу связи:

properties
id, title

products
id, ..., ..., ...

products_properties
property_id, product_id

Тип такого:
CODE (SQL):
скопировать код в буфер обмена
  1. SELECT p.*
  2.     FROM properties pts
  3.     INNER JOIN products_properties ppts
  4.         ON ppts.property_id = pts.id
  5.     INNER JOIN products p
  6.         ON p.id = ppts.product_id
  7.     WHERE pts.title LIKE ...


Sheehave пишет:
Страниц около 3000
Это сраные копейки.
 
 Top
MiksIr
Отправлено: 13 Мая, 2015 - 16:26:00
Post Id


Забанен


Покинул форум
Сообщений всего: 378
Дата рег-ции: Сент. 2014  


Помог: 10 раз(а)

[+]


Я правильно понял, что у вас фильтры по принципу яндекс-маркета, т.е. включив один фильтр вы рассчитываете активность фильтров из других групп?
(Добавление)
Если да, то fixxer на пхпклабе дал верный ответ. Простой оптимизацией вы ничего не решите, берите эластик или что-то вроде этого.


-----
self-banned
 
 Top
DeepVarvar Супермодератор
Отправлено: 13 Мая, 2015 - 16:34:02
Post Id



Активный участник


Покинул форум
Сообщений всего: 10377
Дата рег-ции: Дек. 2008  
Откуда: Альфа Центавра


Помог: 353 раз(а)




А, так ТС закинул удочку сразу на нескольких ресурсах? MiksIr дай сцыль поглядеть что там, ато он крохи инфы какие-то тут выдал.
 
 Top
MiksIr
Отправлено: 13 Мая, 2015 - 16:39:36
Post Id


Забанен


Покинул форум
Сообщений всего: 378
Дата рег-ции: Сент. 2014  


Помог: 10 раз(а)

[+]


Да там не больше инфы. Просто задача известная для тех, кто большие каталоги делал с подобными фильтрами.


-----
self-banned
 
 Top
Sheehave
Отправлено: 13 Мая, 2015 - 16:52:23
Post Id


Новичок


Покинул форум
Сообщений всего: 7
Дата рег-ции: Май 2015  


Помог: 0 раз(а)




Количество страниц ограничили до 3000 с около миллиона, добавив ряд логичных ограничений, раньше оно росло факториально от количества параметров Подмигивание
Количество страниц скорее вытекает из числа комбинаций параметров на странице http://begift[dot]com[dot]ua/chto-podarit/

Изначально они вообще генерировались "на лету" и никак отдельно в базе не хранились. "Кеширование" - это и есть такая же генерация.

Кода много и база большая, попробую описать общую схему.

Мелкий пишет:
Из чего это вытекает?

При поиске слева пишут сколько товаров прибавится или убавится с добавлением параметра - вот на каждый такой параметр и происходит перерасчёт.


DeepVarvar пишет:

properties
id, title

products
id, ..., ..., ...

products_properties
property_id, product_id

Это самая простая и логичная схема, у нас та же структура, за исключением добавившихся категорий:

properties
id,categoty_id, title

products_properties
property_id,categoty_id, product_id

Вся загвоздка в том, что тут идёт комбинация "И" и "ИЛИ"

Например:
На входе имеем поиск по набору параметров
1,2,3,4,5,6

Параметры разбиты по категориям вроде:

1: {1,4},
2: {2,3,6},
3: {5}

На что я генерю SQL вида:

CODE (SQL):
скопировать код в буфер обмена
  1.     SELECT p.*
  2.         FROM products p
  3.         WHERE 1=1
  4.         AND EXISTS (SELECT 1 FROM products_properties ppts WHERE p.id = ppts.product_id AND ppts.property_id IN (1,4)   )
  5.         AND EXISTS (SELECT 1 FROM products_properties ppts WHERE p.id = ppts.product_id AND ppts.property_id IN (2,3,6)   )
  6.         AND EXISTS (SELECT 1 FROM products_properties ppts WHERE p.id = ppts.product_id AND ppts.property_id IN (5)   )


И вот сильно лучше ничего в голову не приходит.


MiksIr пишет:
Я правильно понял, что у вас фильтры по принципу яндекс-маркета, т.е. включив один фильтр вы рассчитываете активность фильтров из других групп?

Где-то так)

Сейчас посмотрю конечно что там за готовые решения предлагают. Изначально не предполагал, что это понадобится - задача вроде несложная Однако
 
 Top
MiksIr
Отправлено: 13 Мая, 2015 - 16:59:55
Post Id


Забанен


Покинул форум
Сообщений всего: 378
Дата рег-ции: Сент. 2014  


Помог: 10 раз(а)

[+]


Задача не сложная, но ресурсоемкая. Т.е. ее можно тупо решить железом. Можно посмотреть на тему всяких оптимизаций, где-то кешом подпереть, но это кардинально ничего не изменит.

(Отредактировано автором: 13 Мая, 2015 - 17:01:05)



-----
self-banned
 
 Top
Sail
Отправлено: 13 Мая, 2015 - 17:08:27
Post Id



Участник


Покинул форум
Сообщений всего: 1131
Дата рег-ции: Февр. 2014  


Помог: 57 раз(а)




Sheehave пишет:
На что я генерю SQL вида:
CODE (SQL):
скопировать код в буфер обмена
  1. SELECT p.*
  2.         FROM products p
  3.         WHERE 1=1
  4.         AND EXISTS (SELECT 1 FROM products_properties ppts WHERE p.id = ppts.product_id AND ppts.property_id IN (1,4)   )
  5.         AND EXISTS (SELECT 1 FROM products_properties ppts WHERE p.id = ppts.product_id AND ppts.property_id IN (2,3,6)   )
  6.         AND EXISTS (SELECT 1 FROM products_properties ppts WHERE p.id = ppts.product_id AND ppts.property_id IN (5)   )
  7.  

Для чего выполнять три одинаковых подзапроса?
---
Ну да. Не вполне одинаковых Улыбка
(Добавление)
Sheehave, сравните с этим:
CODE (SQL):
скопировать код в буфер обмена
  1. SELECT p.* FROM `products` p
  2.  JOIN `products_properties` ppts ON ppts.product_id = p.`id` AND ppts.`property_id` IN (1, 4)
  3.  JOIN `products_properties` ppts2 ON ppts2.product_id = p.`id` AND ppts2.`property_id` IN (2, 3, 6)
  4.  JOIN `products_properties` ppts3 ON ppts3.product_id = p.`id` AND ppts3.`property_id` IN (5)
  5.  GROUP BY p.`id`;

(Отредактировано автором: 13 Мая, 2015 - 17:22:12)

 
 Top
Мелкий Супермодератор
Отправлено: 13 Мая, 2015 - 17:32:08
Post Id



Активный участник


Покинул форум
Сообщений всего: 11926
Дата рег-ции: Июль 2009  
Откуда: Россия, Санкт-Петербург


Помог: 618 раз(а)




Sheehave пишет:
На что я генерю SQL вида:

А субд какая?
Для mysql этот запрос дико тяжёлый. Перепишите на идентичных 3 джойна - уже будет лучше.

Идентичный запрос и должен быть уже ощутимо легче, чтобы сразу в рантайме считаться:
WITH filter AS (
Тьфу, не то.

CODE (SQL):
скопировать код в буфер обмена
  1. SELECT p.*
  2.         FROM products p
  3.         JOIN (
  4.                         SELECT product_id,
  5.                                 sum(property_id IN (1,4)) AS filter_0,
  6.                                 sum(property_id IN (2,3,6)) AS filter_1,
  7.                                 sum(property_id IN (5)) AS filter_2
  8.                         FROM products_properties
  9.                         WHERE property_id IN (1,2,3,4,5,6)
  10.                         GROUP BY product_id
  11.                         HAVING filter_0>0 AND filter_1>0 AND filter_2>0
  12.                         ) AS filters ON p.id=filters.product_id


-----
PostgreSQL DBA
 
 Top
Sail
Отправлено: 13 Мая, 2015 - 17:33:03
Post Id



Участник


Покинул форум
Сообщений всего: 1131
Дата рег-ции: Февр. 2014  


Помог: 57 раз(а)




И добавьте индекс (уникальный, однако, если нет одинаковых id параметра для разных категорий) по `product_id` и `property_id` для таблицы `products_properties` (если вдруг он отсутствует)
 
 Top
Мелкий Супермодератор
Отправлено: 13 Мая, 2015 - 17:36:38
Post Id



Активный участник


Покинул форум
Сообщений всего: 11926
Дата рег-ции: Июль 2009  
Откуда: Россия, Санкт-Петербург


Помог: 618 раз(а)




Sail пишет:
добавьте индекс (уникальный

Первичный сразу. Для таблицы связей отличный вариант сразу ставить первичный составной ключ непосредственно на данные.

Sheehave пишет:
При поиске слева пишут сколько товаров прибавится или убавится с добавлением параметра - вот на каждый такой параметр и происходит перерасчёт.

Что в запросе при этом меняется? Это вполне можно одним запросом вытащить.


-----
PostgreSQL DBA
 
 Top
Sail
Отправлено: 13 Мая, 2015 - 17:41:37
Post Id



Участник


Покинул форум
Сообщений всего: 1131
Дата рег-ции: Февр. 2014  


Помог: 57 раз(а)




Мелкий, спасибо за уточнение Улыбка
А в Вашем запросе осталось только опечатки поправить Закатив глазки
 
 Top
Мелкий Супермодератор
Отправлено: 13 Мая, 2015 - 17:47:23
Post Id



Активный участник


Покинул форум
Сообщений всего: 11926
Дата рег-ции: Июль 2009  
Откуда: Россия, Санкт-Петербург


Помог: 618 раз(а)




Sail пишет:
А в Вашем запросе осталось только опечатки поправить

Запросто мог что-то прошляпить, но что - не вижу. Ткните носом Растерялся


-----
PostgreSQL DBA
 
 Top
Sail
Отправлено: 13 Мая, 2015 - 17:49:51
Post Id



Участник


Покинул форум
Сообщений всего: 1131
Дата рег-ции: Февр. 2014  


Помог: 57 раз(а)




Мелкий, filter_3 и filter_2, produnct_id...
 
 Top
Страниц (2): [1] 2 »
Сейчас эту тему просматривают: 0 (гостей: 0, зарегистрированных: 0)
« Хранение данных, их вывод и обработка »


Все гости форума могут просматривать этот раздел.
Только зарегистрированные пользователи могут создавать новые темы в этом разделе.
Только зарегистрированные пользователи могут отвечать на сообщения в этом разделе.
 



Powered by PHP  Powered By MySQL  Powered by Nginx  Valid CSS  RSS

 
Powered by ExBB FM 1.0 RC1. InvisionExBB