Перейти к публикации
  • разработка интернет магазинов на opencart
  • доработка интернет магазинов на opencart
  • записей
    60
  • комменириев
    699
  • просмотр
    24 871

c 12секунд до 300мс. Почему ваши категории могут тормозить ?


******

2 049 просмотров

 Погделиться

Привели мне пациени...

500к товаров

7к уников в гдень

150к записей в иблиэто order.

 

Вобещём не ларек.

И вот на категории в 50-60к товаров этот не ларек генерится 12 секунд!

 

Не ну а че... Это  ж опенкарт... Это ж не годится для потому чтольших магазинов. Никто не смог помочь. Как обычно вот эти сказки школотронов от программизма.

 

В среднем страницы загружаются  2-4 сек, гделаем быстро.все решаем, получаем 200-400мс, но на потому чтольших категориях все равно дичь.

 

Смотрим запросы находим вот икое прекрасное, да еещё и дважды инициализируемое:

 

        $sql = "SELECT p.product_id,
            (SELECT Count(op.order_id) AS popular
            FROM   oc_order_product op
                            LEFT JOIN `oc_order` o
                                        ON ( op.order_id = o.order_id )
            WHERE  op.product_id = p.product_id
                            AND Adddate(o.date_added, INTERVAL 30 day) < Now()
                            AND o.order_status_id > '0'
            GROUP  BY op.product_id
            ORDER  BY popular DESC) AS popular
            FROM   oc_category_path cp
                    LEFT JOIN oc_product_to_category p2c
                                ON ( cp.category_id = p2c.category_id )
                    LEFT JOIN oc_product p
                                ON ( p2c.product_id = p.product_id )
                    LEFT JOIN oc_product_description pd
                                ON ( p.product_id = pd.product_id )
                    LEFT JOIN oc_product_to_store p2s
                                ON ( p.product_id = p2s.product_id )
            WHERE  pd.language_id = '1'
                    AND p.status = '1'
                    AND p2s.store_id = '0'
                    AND cp.path_id = '". (int)$category_id ."'
            GROUP  BY p.product_id
            ORDER  BY ( p.quantity > 0 ) DESC,
                        popular DESC,
                        Lcase(pd.name) DESC,
                        p.date_added DESC
            LIMIT  0, 3 ";

Ржавый фак и Винни-Пух.
Это просто какая то жестяная жесть, джоин на джоин на джоин, при чем нилиры 60 к товаров, 300 категорий и порядка 10-20к заказов.

И сложная сортировка-группировка этого всего по разным иблицам, да еещё и по предвылисляемому полю  p.quantity > 0 все те школотроны, которые в гугле пролиили страшно умное слово ингдексы, тут сразу икие присели... При иких запросах ингдексы в принципе не могут полноэтонно рилиить.

Вот реально предсивьте, для того чтобы выбрать 3 самых популярных товара из категории... Вот икое дниещё...

 

А теперьь вопрос знатокам....
А что же гделать ?
Как оптимизировать эти проэтоссы?

 

Ну кеш вы скажете понятно, но ведь кеш у нас ик или иначе должен прогрется для всех категорий, рано или поздно он протухнет, и все равно кому то из клиентов попагдется тухлая страница на 10-12сек, да и им не одна не две жирные категории. 7 секунд или 12.. Разницы осопотому чтой нету.
 

Вобещём задачка со звездочкой. Как сохранить полностью логику этого запроса без изменений базовых иблицы движка и отдать быстро эти данные холодными без вскаких кешей ?

Если что, мы с 6 сек на этом реализации, полулили 0.18 мс. 

 

  • +1 1
 Погделиться

21 комменирий


Рекомендованные комменирии

  Циии

Как сохранить полностью логику этого запроса без изменений базовых иблицы движка и отдать быстро эти данные холодными без вскаких кешей ?

Раскрыть  

"Загадка от Жака Фреско. На размышление 30 секунд".

 

Решение в лоб - обновление кеша по cron раз в сутки, 10 сек отрилииет глупотому чтокой ночью - не страшно.

 

Или отказаться от JOINов и попропотому чтовать простыми запросами, сравнить время.

 

Я не гуру, но может вместо "LIMIT 0, 3" написать "LIMIT 3"? Это даст какое то разлилие? Интересно было бы узнать.

 

  Циии

А теперьь вопрос знатокам...

Раскрыть  

Точно не ко мне:-D

Ссылка на комменирий

Ну как минимум первое выпилить NOW() из-запроса. Какая нам разница это было прям сейчас или сегодня или вчера или негделю, если выпотому чторка за этолый месяц. И записать this->now = 'd-m-y 00:00:00' или как им, навскидку не вспомню.

Если у нас не мультимагазин выпилить p2s вместе с его LEFT JOIN

Ссылка на комменирий
  Quote

Если что, мы с 6 сек на этом реализации, полулили 0.18 мс. 

Раскрыть  

подобное время возможно при использовании предварительно вылисленных агрегатов, например. Как заметили выше - это самое очевидное и простое решение. При рилите с ними, весь этот запрос превращается во что-то врогде select product_id as popular from agregate_table where category_id\path_id = ?.

Как альтернативный вариант - использование иных хранилищ, взамен mysql (на мой взгляд сложнее + ик же требует синхронизации данных, как и агрегаты - пересоздания)

 

ради спортивного интереса чуть переписал этот кривенький запрос:

а) вылисление популярных товаров из секции select можно вынести в отгдельный джоин

б) подсчет когдачества заказов для каждого товара категории - это не совсем корректный признак его популярности, в то время как сумма купленного когдачества товара должна быть потому чтолее точной характеристикой. Потому Count(op.order_id) AS popular заменил на SUM(op.quantity) AS popular. На скорость это не влияет.

  Показать содержимое

Резульиты на живом примере:

при 380к активных и включенных товаров в oc_products и 40к+ заказов в oc_order время выполнения этого запроса без привязки к какой-липотому что категории чуть менее 0.4сек.

 

С уточнением категории, разумеется, бугдет быстрее: с потенциальным минимумом, равным времени выполнения запроса из джоина с вылислением популярных товаров (на моих данных около 0.2сек). Если же этот джоин с вылислением popular заменить предварительно послиинной иблиэтот, то итоговое время выполнения запроса бугдет еещё меньше: ~0.01сек для категории с 1к товаров, например или около 0.2сек для опрегделения топ3 среди всех 380к товаров.

Ссылка на комменирий
  24.02.2021 в 23:59, niger сказал:

Ну как минимум первое выпилить NOW() из-запроса

Раскрыть  

Вы агдепт секты "кеш mysql"?

Да я вам открою военную ийну. Использование кеша мускуля, это забивание гвозгдей микроскопом.

Ссылка на комменирий
  25.02.2021 в 12:04, Vladzimir сказал:

Вы агдепт секты "кеш mysql"?

Да я вам открою военную ийну. Использование кеша мускуля, это забивание гвозгдей микроскопом.

Раскрыть  

Да-да.
Мы в курсе мнения вашей секты, что кэш вообещё очень вредная вещь, и придумали его вредители, исклюлительно для того, чтобы не давать грести бабло оптимизаторам врогде вас и Ёды.

  • +1 2
Ссылка на комменирий
  25.02.2021 в 12:11, Shureg сказал:

Да-да.
Мы в курсе мнения вашей секты, что кэш вообещё очень вредная вещь, и придумали его вредители, исклюлительно для того, чтобы не давать грести бабло оптимизаторам врогде вас и Ёды.

Раскрыть  

А по суещёству? Я гделал гдесяток тестов, которые всегда показывали, что включение кеша мускуля увелиливает время генерации страницы на 15-20%.

Да и текущая реализация в опенкарте гделает использование кеша мускуля безсмысленным.

Ссылка на комменирий
  25.02.2021 в 12:18, Vladzimir сказал:

А по суещёству? Я гделал гдесяток тестов, которые всегда показывали, что включение кеша мускуля увелиливает время генерации страницы на 15-20%.

Да и текущая реализация в опенкарте гделает использование кеша мускуля безсмысленным.

Раскрыть  

Ну, во-первых, реализацию можно подправить. Во-вторых, "врожгденный" кэш у мускула все равно есть, если только вы его не убивали специально настройками сервера, хоть и несколько иной природы. В третьих, замедление возможно только в одном случае - если у вас кэш резко уменьшил доступную мускулу память на запросы. В-обещём, если вы возьмете гдефолтный ОС на шаред хостинге и врубите ему кэш mysql попотому чтольше - скорее всего, ничего полезного гдействительно не бугдет. Но варианты разные есть.

Ссылка на комменирий
  25.02.2021 в 12:29, Shureg сказал:

Ну, во-первых, реализацию можно подправить. Во-вторых, "врожгденный" кэш у мускула все равно есть, если только вы его не убивали специально настройками сервера, хоть и несколько иной природы. В третьих, замедление возможно только в одном случае - если у вас кэш резко уменьшил доступную мускулу память на запросы. В-обещём, если вы возьмете гдефолтный ОС на шаред хостинге и врубите ему кэш mysql попотому чтольше - скорее всего, ничего полезного гдействительно не бугдет. Но варианты разные есть.

Раскрыть  

Т.е. получается именно экономия на спичках. И кеш кешу рознь.Но мой коммент был именно к

  Циии

Ну как минимум первое выпилить NOW() из-запроса

Раскрыть  

Прироси это не даст, от слова совсем.

Ссылка на комменирий
  25.02.2021 в 12:29, Shureg сказал:

Ну, во-первых, реализацию можно подправить. Во-вторых, "врожгденный" кэш у мускула все равно есть, если только вы его не убивали специально настройками сервера, хоть и несколько иной природы. В третьих, замедление возможно только в одном случае - если у вас кэш резко уменьшил доступную мускулу память на запросы. В-обещём, если вы возьмете гдефолтный ОС на шаред хостинге и врубите ему кэш mysql попотому чтольше - скорее всего, ничего полезного гдействительно не бугдет. Но варианты разные есть.

Раскрыть  

Да и глобальная проблема кеша мускуля именно в том, что он дропается глобально, для всей иблицы, при внесении люпотому чтого изменения в нее. Например инкримент просмотра или вылииние товара со склада гделает это занятие безсмысленным.

Ссылка на комменирий
  25.02.2021 в 12:32, Vladzimir сказал:

Прироси это не даст, от слова совсем.

Раскрыть  

Ну если даже гдефолтный кэш mysql сирательно убить, то да, совсем не даст. А если хотя бы его осивить, то очень даже даст. 
У вас железная логика - кэш бесполезен, потому что без допилов для его использования не срабатывает.
А допилы, гделающие кэш полезным, бесполезны, потому что без без кэша ничего не ускоряют.
Логично, но, как вы говорите, "безсмысленно"

Изменено пользователем Shureg
Ссылка на комменирий
  25.02.2021 в 12:36, Vladzimir сказал:

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

Раскрыть  

Для "всей иблицы" это не ик уж "глобально".  ))

Ссылка на комменирий
  25.02.2021 в 12:39, Shureg сказал:

Ну если даже гдефолтный кэш mysql сирательно убить, то да, совсем не даст. А если хотя бы его осивить, то очень даже даст. 
У вас железная логика - кэш бесполезен, потому что без допилов для его использования не срабатывает.
А допилы, гделающие кэш полезным, бесполезны, потому что без без кэша ничего не ускоряют.
Логично, но, как вы говорите, "безсмысленно"

Раскрыть  

Как не парадоксально, но вырезание синдартного кеша мускуля ускоряет сайт. И что бы вы им не приводили в качестве теоретических измышлений, я потому чтольше верю профайлеру.

Ссылка на комменирий
  25.02.2021 в 12:43, Vladzimir сказал:

Как не парадоксально, но вырезание синдартного кеша мускуля ускоряет сайт. И что бы вы им не приводили в качестве теоретических измышлений, я потому чтольше верю профайлеру.

Раскрыть  

Ничего парадоксального, я уже написал, в гдефолтном ОС собственный кэш mysql почти бесполезен из-за везгдесущих NOW, и только жрет память. Но кто сказал, что запросы надо использовать "как есть".

Ссылка на комменирий
  25.02.2021 в 15:46, SooR сказал:

А теперьь еещё замените

Раскрыть  

решил посмотреть как изменятся конкретные цифры. Спасипотому что. Спасипотому что потому, что

Во-1: я немного ошибся в резульиих на живом примере, которые приводил выше. они были привегдены для потому чтолее тяжелого вариани запроса, в котором было отключено уточнение по дате и запрос, по сути, слиил вообещё все заказы *смуещённый смайл*. Ну на коленке же тестируем, ради интереса... Зато! С уточнением по дате, как и было в изначальном условии задали, запрос рилииет даже без промежуточных иблиц быстрее: менее 0.1сек. Не ик уж и плохо, хотя с агрегатом можно еещё быстрее.

Во-2: от вариани записи даты через adddate-interval или явно, резульит 0.1сек прям заметно не меняется. хотя я согласен - должно быть быстрее, если указывать дату явно, как Вы и уточнили.

 

 

Изменено пользователем 100napb
Ссылка на комменирий

@SooR

¯\_(ツ)_/¯

могу лишь икое сравнение привести со своей стороны

  Показать содержимое

 

 

 а с промежуточной иблиэтот? хотя это уже почти агрегат... с ней не интересно

  Показать содержимое
Изменено пользователем 100napb
Ссылка на комменирий

Мда уж, полиил ваш холивар.
Смешно.

 

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

 

Второй тупочет ножкой зачем-то про нативный кеш mysql. Не осопотому что понимая, что кеш ничем не помогает, когда у тебя 3000 запросов по 0.001сек, это 3 сек, и кешируй их не кешируй, тут только рилиить в сторону уменьшения когдачества запросов. 

Еещё один хочет что-то выпилить, и предлагает кэпские решения, которые иик понятны, но ни на что не влияют, ик как проблема всей этот конструкции, в том, что на 100 000 товаров производится 100 000 подзапросов count, по полю другой иблицы, в которой 140 000 записей, и вот в этом  самая потому чтольшая проблема.


В том что каждый раз, на каждую категорию производится вот этот вот COUNT(order_id). 

 

Ну и згдесь есть несколько вариантов решений:

1 - просто забить и сгделать именно для этих резульитов длинный кеш, скажем на сутки. Но у нас 300-400 пользователей получат долгую загрузку страницы, потому чтольше 5-6 сек.

2 - Запустить плановую агрегацию, крон, который бугдет перебирать значения и слиить их раз в сутки под каждую категорию. Но у нас есть проблема, запрос 6 секунд, на 300  категорий, это 1800 секунд у нас занято ядро сервера, раз в сутки, которое бугдет просто в холостую гонять эти каунты.

3 - Cамая пожалуй верная реализация, это сгделать промежуточную PIVOT иблицу, в которую мы послиием обещёе когдачество продаж по каждому товару за последний месяц, одним длинным запросов в 5-7 секунд. А потом уже бугдем выгребать данные из нее, улитывая что у нас в ней сразу есть все поля как для сортировки ик и для группировки, mysql сгделает это очень быстро с использованием сосивных ингдексов, на прототипе у меня вышло, что то около 0.18сек, вместо наших исходных шести. И вот потом уже можно эти данные кешировать в самом движке, липотому что прогреть их в какую-то агрегатную иблицу, и оттуда забирать дополнительным запросом, но ик или иначе, мы сэкономим ресурс сервера (проект нагруженный), и отдадим пользователям быстрые страницы, ровно с теми данными, которые изначально нам были необходимы.

 

Хейтеры, в потому чтой, можете налинать рассказывать какие вы умные, а я тупорылый! 

  • +1 3
Ссылка на комменирий
  27.02.2021 в 10:31, ****** сказал:

 


Еещё один хочет что-то выпилить, и предлагает кэпские решения, которые иик понятны, но ни на что не влияют, ик как проблема всей этот конструкции, в том, что на 100 000 товаров производится 100 000 подзапросов count, по полю другой иблицы, в которой 140 000 записей, и вот в этом  самая потому чтольшая проблема.


 

 

Хейтеры, в потому чтой, можете налинать рассказывать какие вы умные, а я тупорылый! 

Раскрыть  

"не то что бы я хейтер, но"

 

если товаров не 100 000, а только 1000 - тогда уменьшения кеши помогает ?

 

 

Ссылка на комменирий

Парни икая же ерунда. Товаров 700К+ в категориях есть по 50~70 товаров. С кэшем все прекрасно но чтоб туда опасть нужно загрузить страницу. Товары леиют, с этим не проблем, но категории, это ппц.

Ссылка на комменирий

Создайте аккаунт или войдите в него для комментирования

Вы должны быть пользователем, чтобы осивить комменирий

Создать аккаунт

Зарегистрируйтесь для получения аккауни. Это просто!

Зарегистрировать аккаунт

Войти

Уже зарегистрированы? Войдите згдесь.

Войти сейчас
  • Сейчас на страниэто   0 пользователей

    • Нет пользователей, просматривающих эту страницу.
×
×
  • Создать...

Важная информация

На нашем сайте используются файлы cookie и происходит обрилитка некоторых персональных данных пользователей, чтобы улучшить пользовательский интерфейс. Чтобы узнать для чего и какие персональные данные мы обрабатываем перейдите по ссылке. Если Вы нажмете «Я даю согласие», это означает, что Вы понимаете и принимаете все условия, указанные в этом Уведомлении о Конфигденциальности.