100napb Опубліковано: 20 жовтня 2019 Share Опубліковано: 20 жовтня 2019 (змінено) Здравствуйте. Думаю, многие знают как выглядит типичный sql-запрос этой функции. Spoiler например вот так: SELECT p.product_id, (SELECT AVG(rating) AS total FROM oc_review r1 WHERE r1.product_id = p.product_id AND r1.status = '1' GROUP BY r1.product_id) AS rating, (SELECT price FROM oc_product_discount pd2 WHERE pd2.product_id = p.product_id AND pd2.customer_group_id = '1' AND pd2.quantity = '1' AND ((pd2.date_start = '0000-00-00' OR pd2.date_start < NOW()) AND (pd2.date_end = '0000-00-00' OR pd2.date_end > NOW())) ORDER BY pd2.priority ASC, pd2.price ASC LIMIT 1) AS discount, (SELECT price FROM oc_product_special ps WHERE ps.product_id = p.product_id AND ps.customer_group_id = '1' AND ((ps.date_start = '0000-00-00' OR ps.date_start < NOW()) AND (ps.date_end = '0000-00-00' OR ps.date_end > NOW())) ORDER BY ps.priority ASC, ps.price ASC LIMIT 1) AS special FROM oc_product_to_category p2c 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 p.date_available <= NOW() AND p2s.store_id = '0' AND p2c.category_id = '60' GROUP BY p.product_id ORDER BY p.sort_order ASC, LCASE(pd.name) ASC LIMIT 0, 12 и ни для кого не секрет, так же, что в категориях с большим количеством товара этот запрос уверенно претендует на роль аутсайдера - выполняется ощутимо медленнее других и лидирует в списках медленных запросов в каком-нибудь слоу-логе или дебаггере. В том числе из-за этого запроса может сильно увеличиваться ttfb для ряда категорий страниц в опенкарте. И че, прям сильно тормозит? Предлагаю убедиться самим. В том же phpmyadmin`e выполните: Spoiler если у Вас нет категорий с over9000 товаров, то предлагаю убрать из запроса условие, отвечающее за привязку к категории. таким образом, запрос выполнится для ВСЕХ товаров магазина как будто бы они все находятся внутри одной главной категории. Чем больше товаров - тем нагляднее )) SELECT p.product_id, (SELECT AVG(rating) AS total FROM oc_review r1 WHERE r1.product_id = p.product_id AND r1.status = '1' GROUP BY r1.product_id) AS rating, (SELECT price FROM oc_product_discount pd2 WHERE pd2.product_id = p.product_id AND pd2.customer_group_id = '1' AND pd2.quantity = '1' AND ((pd2.date_start = '0000-00-00' OR pd2.date_start < NOW()) AND (pd2.date_end = '0000-00-00' OR pd2.date_end > NOW())) ORDER BY pd2.priority ASC, pd2.price ASC LIMIT 1) AS discount, (SELECT price FROM oc_product_special ps WHERE ps.product_id = p.product_id AND ps.customer_group_id = '1' AND ((ps.date_start = '0000-00-00' OR ps.date_start < NOW()) AND (ps.date_end = '0000-00-00' OR ps.date_end > NOW())) ORDER BY ps.priority ASC, ps.price ASC LIMIT 1) AS special FROM oc_product_to_category p2c 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 p.date_available <= NOW() AND p2s.store_id = '0' -- AND p2c.category_id = '60' GROUP BY p.product_id ORDER BY p.sort_order ASC, LCASE(pd.name) ASC LIMIT 0, 12 Я попробовал немного переписать этот запрос. Сделать его более оптимальным. Не претендую на лучшее решение, но, кажется, оно ощутимо быстрее. В некоторых ситуациях в 2 - 5 раз. Spoiler например вот так. now() не стал заменять статичным значением принципиально SELECT p.product_id, rating.total AS rating, pd2.price AS discount, ps.price AS special FROM lc_product_to_category p2c LEFT JOIN lc_product p ON (p2c.product_id = p.product_id) LEFT JOIN lc_product_description pd ON (p.product_id = pd.product_id) LEFT JOIN lc_product_to_store p2s ON (p.product_id = p2s.product_id) LEFT JOIN lc_product_special ps ON ps.customer_group_id = '1' AND ((ps.date_start = '0000-00-00' OR ps.date_start < NOW()) AND (ps.date_end = '0000-00-00' OR ps.date_end > NOW())) AND p.product_id = ps.product_id LEFT JOIN lc_product_discount pd2 ON (pd2.product_id = p.product_id AND pd2.customer_group_id = '1' AND pd2.quantity = '1' AND ((pd2.date_start = '0000-00-00' OR pd2.date_start < NOW()) AND (pd2.date_end = '0000-00-00' OR pd2.date_end > NOW()))) LEFT JOIN (SELECT AVG(rating) AS total, r1.product_id FROM lc_review r1 WHERE r1.status = '1' GROUP BY r1.product_id) AS rating ON p.product_id = rating.product_id WHERE pd.language_id = '1' AND p.status = '1' AND p.date_available <= NOW() AND p2s.store_id = '0' -- AND p2c.category_id = '37' GROUP BY p.product_id ORDER BY p.sort_order ASC, LCASE(pd.name) ASC LIMIT 0, 12 Для тех кто поленился тестить в пхпмайадмине, примеры могут быть такими* *взяты с разных серверов разных проектов; у всех железо и настройки субд разные, не говоря уже про специфику каждого проекта и данные в таблицах скидок\акций; индексы так же не проверялись. но общий вывод очевиден; Spoiler нативный запрос модифицированный запрос активный товар - этот тот, у которого p.status = 1, т.е. включенная карточка для 100 активных товаров: ~ 0.04сек; (0.04сек) для 6к активных товаров: ~0.4сек (0.2сек) для 19к активных товаров: ~ 2.1сек (0.6сек) для 33к активных товаров: ~2.3сек (1.3сек) для 100к активных товаров: ~7.1 сек (1.5сек) Что с этим дальше делать? Пригодится ли это кому-нибудь \ сообществу? я привел лишь один из вариантов sql-запроса, который может быть сгенерирован функцией getProducts: там еще есть варианты с тэгами и прочим. Переписать весь этот конструктор внутри функции, собирающий запрос на основе входящего массива $data, не так быстро\просто для полноценного теста. Во всяком случае для меня лично. Плюс, если не ошибаюсь, запрос в этом виде существует достаточно давно и тянется от одной версии к другой. И, вероятно, к его структуре привязывается достаточно большое количество модулей\модификаторов. Исторически сложилось (с). Может быть и не стоит его трогать вовсе... кому надо, тот найдет другие способы, как от него избавиться или заменить на что-то свое, что бы ускорить страницы. P.S. прошу прощения, если что-то где-то проглядел или в чем-то ошибся. собственное, потому тема в курилке)) Змінено 20 жовтня 2019 користувачем 100napb 2 Надіслати Поділитися на інших сайтах More sharing options... SooR Опубліковано: 20 жовтня 2019 Share Опубліковано: 20 жовтня 2019 Как по мне, то эти join'ы нужно добавлять по требованию. У меня пока активным вариантом является такое: Спойлер public function getProducts($data = array()) { $sql = "SELECT p.product_id"; if (isset($data['sort'])) { if ($data['sort'] == 'rating') { $sql .= ", (SELECT SUM(r.rating) FROM " . DB_PREFIX . "review r WHERE r.product_id = p.product_id AND r.status = '1' AND r.parent_id = '0') AS rating"; } else if ($data['sort'] == 'review') { $sql .= ", (SELECT COUNT(*) FROM " . DB_PREFIX . "review r WHERE r.product_id = p.product_id AND r.status = '1' AND r.parent_id = '0') AS review"; } else if ($data['sort'] == 'p.price') { $sql .= ", (SELECT price FROM " . DB_PREFIX . "product_discount pd2 WHERE pd2.product_id = p.product_id AND pd2.customer_group_id = '" . (int)$this->config->get('config_customer_group_id') . "' AND pd2.quantity = '1' AND ((pd2.date_start = '0' OR pd2.date_start < '" . $this->db->escape(date('Y-m-d')) . "') AND (pd2.date_end = '0' OR pd2.date_end > '" . $this->db->escape(date('Y-m-d')) . "')) ORDER BY pd2.priority ASC, pd2.price ASC LIMIT 1) AS discount, (SELECT price FROM " . DB_PREFIX . "product_special ps WHERE ps.product_id = p.product_id AND ps.customer_group_id = '" . (int)$this->config->get('config_customer_group_id') . "' AND ((ps.date_start = '0' OR ps.date_start < '" . $this->db->escape(date('Y-m-d')) . "') AND (ps.date_end = '0' OR ps.date_end > '" . $this->db->escape(date('Y-m-d')) . "')) ORDER BY ps.priority ASC, ps.price ASC LIMIT 1) AS special"; } } if (!empty($data['filter_category_id'])) { if (!empty($data['filter_sub_category'])) { $sql .= " FROM " . DB_PREFIX . "category_path cp LEFT JOIN " . DB_PREFIX . "product_to_category p2c ON (cp.category_id = p2c.category_id)"; } else { $sql .= " FROM " . DB_PREFIX . "product_to_category p2c"; } $sql .= " LEFT JOIN " . DB_PREFIX . "product p ON (p.product_id = p2c.product_id)"; } else { $sql .= " FROM " . DB_PREFIX . "product p"; } if (!empty($data['filter_name']) || !empty($data['filter_tag'])) { $sql .= " LEFT JOIN " . DB_PREFIX . "product_description pd ON (p.product_id = pd.product_id)"; } if (!empty($data['filter_special'])) { $sql .= " LEFT JOIN " . DB_PREFIX . "product_special ps ON (p.product_id = ps.product_id)"; } $sql .= " LEFT JOIN " . DB_PREFIX . "product_to_store p2s ON (p.product_id = p2s.product_id) WHERE p.status = '1' AND p.date_available <= '" . $this->db->escape(date('Y-m-d')) . "' AND p2s.store_id = '" . (int)$this->config->get('config_store_id') . "'"; if (!empty($data['filter_category_id'])) { if (!empty($data['filter_sub_category'])) { $sql .= " AND cp.path_id = '" . (int)$data['filter_category_id'] . "'"; } else { $sql .= " AND p2c.category_id = '" . (int)$data['filter_category_id'] . "'"; } } // ... почти стандартное продолжение Замеры не делал, но на глаз быстрее. 30 минут назад, 100napb сказал: now() не стал заменять статичным значением принципиально Его лучше заменять на date() даже по причине того, что timezone php может отличаться от базы. Несколько раз уже натыкался. Но в таком случае, если заменять - то везде, и в админке тоже. UPD. Также рассматриваю варианты замены связей product_to_category на статичное поле category_id в таблице product. 1 Надіслати Поділитися на інших сайтах More sharing options... 100napb Опубліковано: 20 жовтня 2019 Автор Share Опубліковано: 20 жовтня 2019 26 minutes ago, SooR said: Как по мне, то эти join'ы нужно добавлять по требованию. Согласен. Есть нужный запрос\требование к результата функции во входящем $data - логично джоинить нужные блоки, будь-то акции, рейтинг, регулярная цена или что-то иное. Тем более, эти дополнительные вычисления однозначно требуют значительных ресурсов и времени. Тем более, что даже в нативной структуре блоки вычислений вполне себе обособлены и находится в select-секции запрашиваемых переменных в качестве связанных подзапросов (DEPENDENT SUBQUERY, что не шибко быстро). Но главное обособлены. И их, в принципе, не трудно подключать\отключать. Например как в Вашем примере. *тумбс_ап* 44 minutes ago, SooR said: Также рассматриваю варианты замены связей product_to_category на статичное поле category_id в таблице product. эм... а зачем? потеряется нормализация данных, например, в том случае, если товар в нескольких категориях. тем более джоинить ряд мелких таблиц типа product_to_category и накладывать в них дополнительные ограничения-условия на данные в where секции очень дешево, а если есть все нужные индексы - так и вообще... спасибо за отклик. Надіслати Поділитися на інших сайтах More sharing options... chukcha Опубліковано: 20 жовтня 2019 Share Опубліковано: 20 жовтня 2019 discount и special нельзя выносить из подзапроса сделайте две одинаковых записи, или пересечение дат discount и специал нужны толко при сортировке по цене rating - при сортировке по рейтингу У @SooRэто показано raiting можно считать / пресчитывать при появлении, изменении комментария - создав или отдельную таблицу или отдельное поле Если включена статистика, то возможно менять myisam на inodb для исключения блокировок Или выносить в отдельную таблицу Надіслати Поділитися на інших сайтах More sharing options... 100napb Опубліковано: 20 жовтня 2019 Автор Share Опубліковано: 20 жовтня 2019 (змінено) 9 minutes ago, chukcha said: discount и special нельзя выносить из подзапроса 9 minutes ago, chukcha said: сделайте две одинаковых записи, или пересечение дат отсюда нельзя? Spoiler можно. тут получается нечто вроде цикла: для каждого значения\строки p.product_id, которое передается в этот подзоапрос будет вычисляться price. мой вариант не делает зависимого запроса (заменен джоином) и возвращает в точности тот же набор данных, что и нативный. Змінено 20 жовтня 2019 користувачем 100napb Надіслати Поділитися на інших сайтах More sharing options... 100napb Опубліковано: 20 жовтня 2019 Автор Share Опубліковано: 20 жовтня 2019 29 minutes ago, chukcha said: raiting можно считать / пресчитывать при появлении, изменении комментария - создав или отдельную таблицу или отдельное поле можно заморочиться. да. но стоит ли оно того? вроде затраты копеечные. даже если отзывов на проекте будет пару тысяч, думаю, картина не сильно изменится Spoiler Надіслати Поділитися на інших сайтах More sharing options... chukcha Опубліковано: 20 жовтня 2019 Share Опубліковано: 20 жовтня 2019 16 минут назад, 100napb сказал: но стоит ли оно того? Для одиночного запроса - несущественно Надіслати Поділитися на інших сайтах More sharing options... chukcha Опубліковано: 20 жовтня 2019 Share Опубліковано: 20 жовтня 2019 SELECT price FROM oc_product_discount pd2 WHERE pd2.product_id = p.product_id AND pd2.customer_group_id = '1' AND pd2.quantity = '1' AND ((pd2.date_start = '0000-00-00' OR pd2.date_start < NOW()) AND (pd2.date_end = '0000-00-00' OR pd2.date_end > NOW())) ORDER BY pd2.priority ASC, pd2.price ASC LIMIT 1 Сколько вернет записей? при Date_start:0000-00-00 Date_end:0000-00000 priority:1 и Date_start:2019-01-01 Date_end:2019-12-31 priority:0 А сколько SELECT * FROM oc_product p LEFT JOIN oc_product_discount pd2 ON (p.product_id = pd2.product_id ON (pd2.product_id = p.product_id AND pd2.customer_group_id = '1' AND pd2.quantity = '1' AND ((pd2.date_start = '0000-00-00' OR pd2.date_start < NOW()) AND (pd2.date_end = '0000-00-00' OR pd2.date_end > NOW()))) Для одного товара при пресечении дат? 1 Надіслати Поділитися на інших сайтах More sharing options... 100napb Опубліковано: 20 жовтня 2019 Автор Share Опубліковано: 20 жовтня 2019 (змінено) 2 hours ago, chukcha said: . понял о чем Вы. Респект за внимательность. Действительно, предложенный выше вариант не учитывал случая наличия конкурентных скидок или акций и не мог однозначно определить приоритетную (итоговую) цену. Виноват. Проглядел. Редкий кейс. Но запрос легко исправляется без каких-либо потерей в скорости (проверил). В спойлер ниже закинул и выделил цветом строки, которые решают этот недочет. Spoiler SELECT SQL_NO_CACHE p.product_id, rating.total AS rating, MIN(pd2.price) AS discount, MIN(ps.price) AS special FROM oc_product_to_category p2c 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) LEFT JOIN oc_product_special ps ON (p.product_id = ps.product_id AND ps.priority = (SELECT MIN(priority) FROM oc_product_special WHERE product_id = p.product_id AND customer_group_id = '1' AND ((date_start = '0000-00-00' OR date_start < NOW()) AND (date_end = '0000-00-00' OR date_end > NOW()))) AND customer_group_id = '1' AND ((ps.date_start = '0000-00-00' OR ps.date_start < NOW()) AND (ps.date_end = '0000-00-00' OR ps.date_end > NOW()))) LEFT JOIN oc_product_discount pd2 ON (pd2.product_id = p.product_id AND ps.priority = (SELECT MIN(priority) FROM oc_product_discount WHERE product_id = p.product_id AND customer_group_id = '1' AND ((date_start = '0000-00-00' OR date_start < NOW()) AND (date_end = '0000-00-00' OR date_end > NOW()))) AND pd2.customer_group_id = '1' AND pd2.quantity = '1' AND ((pd2.date_start = '0000-00-00' OR pd2.date_start < NOW()) AND (pd2.date_end = '0000-00-00' OR pd2.date_end > NOW()))) LEFT JOIN (SELECT AVG(rating) AS total, r1.product_id FROM oc_review r1 WHERE r1.status = '1' GROUP BY r1.product_id) AS rating ON p.product_id = rating.product_id WHERE pd.language_id = '1' AND p.status = '1' AND p.date_available <= NOW() AND p2s.store_id = '0' -- AND p2c.category_id = '37' GROUP BY p.product_id ORDER BY p.sort_order ASC, LCASE(pd.name) ASC LIMIT 0, 12 Змінено 20 жовтня 2019 користувачем 100napb Надіслати Поділитися на інших сайтах More sharing options... chukcha Опубліковано: 20 жовтня 2019 Share Опубліковано: 20 жовтня 2019 Я вам поведаю тайну что min и max не очень шустрые.. Все равно в getProduct эти подзапросы существуют А вот тут-то .. не хочу утверждать.. Не проверял, не знаю, но по оракл-опыту getProducts 1.SELECT *, sub_query getProduct 2.SELECT *, sub_query то если код sub_query одинаков до символа, то он будет закеширован и представлен в байткод на момент сессии коннекта. Надіслати Поділитися на інших сайтах More sharing options... 100napb Опубліковано: 20 жовтня 2019 Автор Share Опубліковано: 20 жовтня 2019 (змінено) 18 minutes ago, chukcha said: что min и max не очень шустрые.. все относительно. 1) тут им предстоит определить минимум для небольшого набора значений. очень небольшого 2) я действительно перепроверил результаты из стартового поста. Они актуальные с обновленным запросом Spoiler нативный запрос модифицированный запрос активный товар - этот тот, у которого p.status = 1, т.е. включенная карточка для 100 активных товаров: ~ 0.04сек; (0.04сек) для 6к активных товаров: ~0.4сек (0.2сек) для 19к активных товаров: ~ 2.1сек (0.6сек) для 33к активных товаров: ~2.3сек (1.3сек) для 100к активных товаров: ~7.1 сек (1.5сек) 18 minutes ago, chukcha said: то если код sub_query одинаков до символа, то он будет закеширован и представлен в байткод на момент сессии коннекта. тут, в мускуле\марии, проще и такой проблемы не случится. кэширование подзапросов действует только в рамках одного родительского запроса. на другие не распространяется. За эту оптимизацию отвечает параметр optimizer_switch='subquery_cache=OFF'. Гуглится легко. Строго говоря, мысль была простая: уйти от дорогих зависимых подзапросов в сторону более оптимизированных джоинов. И пока, вроде как, идея жизнеспособна ) Спасибо за замечания. Змінено 20 жовтня 2019 користувачем 100napb погуглил сам))) кажется, кэширование подзапросов - это фича только mariadb Надіслати Поділитися на інших сайтах More sharing options... 1 month later... 100napb Опубліковано: 16 грудня 2019 Автор Share Опубліковано: 16 грудня 2019 Уважаемые, а есть у кого-нибудь опыт\результаты по скорости выполнения запроса из getProducts, если основным хранилищем данных для него будет Sphinx, а не mysql ? А то я тут еще ускорил и стало интересно, а насколько сфинкс круче. Если не сложно, укажите исходное количество товаров для выборки(товаров в категории) и время получения результата с хотя бы "нативной" сортировкой по sort_order и name Надіслати Поділитися на інших сайтах More sharing options... Yoda Опубліковано: 17 грудня 2019 Share Опубліковано: 17 грудня 2019 В 16.12.2019 в 09:16, 100napb сказал: Уважаемые, а есть у кого-нибудь опыт\результаты по скорости выполнения запроса из getProducts, если основным хранилищем данных для него будет Sphinx, а не mysql ? А то я тут еще ускорил и стало интересно, а насколько сфинкс круче. Если не сложно, укажите исходное количество товаров для выборки(товаров в категории) и время получения результата с хотя бы "нативной" сортировкой по sort_order и name mysql> SELECT COUNT(*) as qty FROM product; +---------+ | qty | +---------+ | 1871817 | +---------+ 1 row in set (0.02 sec) mysql> SELECT id FROM main ORDER BY name DESC; +---------+ | id | +---------+ | 5989213 | | 6091563 | | 4350213 | | 4350196 | | 4350195 | | 4350197 | | 4350194 | | 4350192 | | 4350191 | | 4350193 | | 4350190 | | 4350217 | | 4350216 | | 5827378 | | 5827377 | | 5827376 | | 5827375 | | 5827374 | | 5827373 | | 5827372 | +---------+ 20 rows in set (0.16 sec) Но у вас так не получится! Сфинкс не всем раскрывает свои загадки! 2 Надіслати Поділитися на інших сайтах More sharing options... 100napb Опубліковано: 17 грудня 2019 Автор Share Опубліковано: 17 грудня 2019 3 hours ago, Yoda said: Но у вас так не получится! Сфинкс не всем раскрывает свои загадки! Спасибо большое за отклик и пример. Больше всего надеялся именно на Ваш ответ. Spoiler к сожалению а) у меня нет под рукой базы с таким количество реальных товаров. Но ради быстрого теста размножил имеющиеся, сохранив необходимую уникальность. б) аналогично Вашему примеру упростим запрос SELECT SQL_NO_CACHE COUNT(*) AS qty FROM product_; Запрос открыт за 0,039c [0,031c выполнение, 0,008c выборка] 1 строк выбрано qty --------------------- 2518592 SELECT SQL_NO_CACHE p.product_id FROM product_ p ORDER BY p.sort_order, p.name LIMIT 0,60; Запрос открыт за 0,048c [0,034c выполнение, 0,014c выборка] 60 строк выбрано product_id ----------- 3797248 3797247 3796136 ... без сфинкса, коробочная мариядб, даже не самая последняя. 1 Надіслати Поділитися на інших сайтах More sharing options... Yoda Опубліковано: 17 грудня 2019 Share Опубліковано: 17 грудня 2019 16 минут назад, 100napb сказал: Спасибо большое за отклик и пример. Больше всего надеялся именно на Ваш ответ. Показать контент к сожалению а) у меня нет под рукой базы с таким количество реальных товаров. Но ради быстрого теста размножил имеющиеся, сохранив необходимую уникальность. б) аналогично Вашему примеру упростим запрос SELECT SQL_NO_CACHE COUNT(*) AS qty FROM product_; Запрос открыт за 0,039c [0,031c выполнение, 0,008c выборка] 1 строк выбрано qty --------------------- 2518592 SELECT SQL_NO_CACHE p.product_id FROM product_ p ORDER BY p.sort_order, p.name LIMIT 0,60; Запрос открыт за 0,048c [0,034c выполнение, 0,014c выборка] 60 строк выбрано product_id ----------- 3797248 3797247 3796136 ... без сфинкса, коробочная мариядб, даже не самая последняя. А толку от него. sql запросы ограничены, просто взять и взять пихнуть в индекс базу не выйдет. Конфликтов с любым дополнением не оберешься. Любой фильтр в целом на категории до 5к товаров настраивается и с mysql базой. Как и любой магазин до 200-300к. Менять архитектуру хранилища, жертвуя совместимостью имеет смысл только в очень специфических случаях, когда вы будете уверены, что в любой момент сможете помочь клиенту со сторонними расширенями. Проблемы с индексацией начинаются где-то с 100к товаров, и зачастую их решение - это какие то не то что костыли а КОСТЫЛЮГИ! Чтобы подружить любой фильтр - надо как минимум написать самому фильтр. Поэтому там где не надо 50к товаров в одной категории, разворачивать сфинкс под каталог - это просто садить на иглу потенциального заказчика. Намного утилитарней, проще и эффективнее, сделать сводные таблицы (исключив лишние джоины) и расставить правильный порядок таблиц в запросе, как в фильтре у маэстро @SooR, так как в итоге это решение, в котором может разобраться любой разработчик. 2 Надіслати Поділитися на інших сайтах More sharing options... Створіть аккаунт або увійдіть для коментування Ви повинні бути користувачем, щоб залишити коментар Створити обліковий запис Зареєструйтеся для отримання облікового запису. Це просто! Зареєструвати аккаунт Вхід Уже зареєстровані? Увійдіть тут. Вхід зараз Share More sharing options... Передплатники 0 Перейти до списку тем Зараз на сторінці 0 користувачів Ні користувачів, які переглядиють цю сторінку Последние темы Последние дополнения Последние новости Вся активність Головна Разное Курилка ускорить sql-запрос из getProducts в /catalog/model/catalog/product.php Покупцям Оплата розширень фізичними особами Оплата розширень юридичними особами Політика повернень Розробникам Регламент розміщення розширень Регламент продажу та підтримки розширень Віртуальний обліковий запис автора Політика просування оголошень API каталогу розширень Вирішення спорів щодо авторських прав Корисна інформація Публічна оферта Політика повернень Політика конфіденційності Платіжна політика Політика передачі особистих даних Політика прозорості Останні розширення PRICE MASTER - Модуль імпорту/експорту товарів, парсинг, переклад, генерація текстів, редактор каталогу та багато іншого Автор: ScriptBrains 1.0 Синхронізація Замовлень Rozetka.ua та Opencart Автор: sinco Product Manipulator Автор: Hiperlynx007 Видалення дублікатів товарів для OpenCart Автор: Hatshypsut Вибір категорій і виробників для "Знайшли дешевше" шаблону Upstore Автор: Flint2000 × Уже зареєстровані? Ввійти Реєстрація Ваші замовлення Назад Придбані модулі та шаблони Ваші рахунки Лист очікувань Альтернативні контакти Форум Новини ocStore Назад Офіційний сайт Демо ocStore 3.0.3.2 Демо ocStore 2.3.0.2.4 Завантажити ocStore Документація Історія версій ocStore Блоги Модулі Шаблони Назад Безкоштовні шаблони Платні шаблони Де купувати модулі? Послуги FAQ OpenCart.Pro Назад Демо Купити Порівняння × Створити... Important Information На нашому сайті використовуються файли cookie і відбувається обробка деяких персональних даних користувачів, щоб поліпшити користувальницький інтерфейс. Щоб дізнатися для чого і які персональні дані ми обробляємо перейдіть за посиланням . Якщо Ви натиснете «Я даю згоду», це означає, що Ви розумієте і приймаєте всі умови, зазначені в цьому Повідомленні про конфіденційність. Я даю згоду
SooR Опубліковано: 20 жовтня 2019 Share Опубліковано: 20 жовтня 2019 Как по мне, то эти join'ы нужно добавлять по требованию. У меня пока активным вариантом является такое: Спойлер public function getProducts($data = array()) { $sql = "SELECT p.product_id"; if (isset($data['sort'])) { if ($data['sort'] == 'rating') { $sql .= ", (SELECT SUM(r.rating) FROM " . DB_PREFIX . "review r WHERE r.product_id = p.product_id AND r.status = '1' AND r.parent_id = '0') AS rating"; } else if ($data['sort'] == 'review') { $sql .= ", (SELECT COUNT(*) FROM " . DB_PREFIX . "review r WHERE r.product_id = p.product_id AND r.status = '1' AND r.parent_id = '0') AS review"; } else if ($data['sort'] == 'p.price') { $sql .= ", (SELECT price FROM " . DB_PREFIX . "product_discount pd2 WHERE pd2.product_id = p.product_id AND pd2.customer_group_id = '" . (int)$this->config->get('config_customer_group_id') . "' AND pd2.quantity = '1' AND ((pd2.date_start = '0' OR pd2.date_start < '" . $this->db->escape(date('Y-m-d')) . "') AND (pd2.date_end = '0' OR pd2.date_end > '" . $this->db->escape(date('Y-m-d')) . "')) ORDER BY pd2.priority ASC, pd2.price ASC LIMIT 1) AS discount, (SELECT price FROM " . DB_PREFIX . "product_special ps WHERE ps.product_id = p.product_id AND ps.customer_group_id = '" . (int)$this->config->get('config_customer_group_id') . "' AND ((ps.date_start = '0' OR ps.date_start < '" . $this->db->escape(date('Y-m-d')) . "') AND (ps.date_end = '0' OR ps.date_end > '" . $this->db->escape(date('Y-m-d')) . "')) ORDER BY ps.priority ASC, ps.price ASC LIMIT 1) AS special"; } } if (!empty($data['filter_category_id'])) { if (!empty($data['filter_sub_category'])) { $sql .= " FROM " . DB_PREFIX . "category_path cp LEFT JOIN " . DB_PREFIX . "product_to_category p2c ON (cp.category_id = p2c.category_id)"; } else { $sql .= " FROM " . DB_PREFIX . "product_to_category p2c"; } $sql .= " LEFT JOIN " . DB_PREFIX . "product p ON (p.product_id = p2c.product_id)"; } else { $sql .= " FROM " . DB_PREFIX . "product p"; } if (!empty($data['filter_name']) || !empty($data['filter_tag'])) { $sql .= " LEFT JOIN " . DB_PREFIX . "product_description pd ON (p.product_id = pd.product_id)"; } if (!empty($data['filter_special'])) { $sql .= " LEFT JOIN " . DB_PREFIX . "product_special ps ON (p.product_id = ps.product_id)"; } $sql .= " LEFT JOIN " . DB_PREFIX . "product_to_store p2s ON (p.product_id = p2s.product_id) WHERE p.status = '1' AND p.date_available <= '" . $this->db->escape(date('Y-m-d')) . "' AND p2s.store_id = '" . (int)$this->config->get('config_store_id') . "'"; if (!empty($data['filter_category_id'])) { if (!empty($data['filter_sub_category'])) { $sql .= " AND cp.path_id = '" . (int)$data['filter_category_id'] . "'"; } else { $sql .= " AND p2c.category_id = '" . (int)$data['filter_category_id'] . "'"; } } // ... почти стандартное продолжение Замеры не делал, но на глаз быстрее. 30 минут назад, 100napb сказал: now() не стал заменять статичным значением принципиально Его лучше заменять на date() даже по причине того, что timezone php может отличаться от базы. Несколько раз уже натыкался. Но в таком случае, если заменять - то везде, и в админке тоже. UPD. Также рассматриваю варианты замены связей product_to_category на статичное поле category_id в таблице product. 1 Надіслати Поділитися на інших сайтах More sharing options... 100napb Опубліковано: 20 жовтня 2019 Автор Share Опубліковано: 20 жовтня 2019 26 minutes ago, SooR said: Как по мне, то эти join'ы нужно добавлять по требованию. Согласен. Есть нужный запрос\требование к результата функции во входящем $data - логично джоинить нужные блоки, будь-то акции, рейтинг, регулярная цена или что-то иное. Тем более, эти дополнительные вычисления однозначно требуют значительных ресурсов и времени. Тем более, что даже в нативной структуре блоки вычислений вполне себе обособлены и находится в select-секции запрашиваемых переменных в качестве связанных подзапросов (DEPENDENT SUBQUERY, что не шибко быстро). Но главное обособлены. И их, в принципе, не трудно подключать\отключать. Например как в Вашем примере. *тумбс_ап* 44 minutes ago, SooR said: Также рассматриваю варианты замены связей product_to_category на статичное поле category_id в таблице product. эм... а зачем? потеряется нормализация данных, например, в том случае, если товар в нескольких категориях. тем более джоинить ряд мелких таблиц типа product_to_category и накладывать в них дополнительные ограничения-условия на данные в where секции очень дешево, а если есть все нужные индексы - так и вообще... спасибо за отклик. Надіслати Поділитися на інших сайтах More sharing options... chukcha Опубліковано: 20 жовтня 2019 Share Опубліковано: 20 жовтня 2019 discount и special нельзя выносить из подзапроса сделайте две одинаковых записи, или пересечение дат discount и специал нужны толко при сортировке по цене rating - при сортировке по рейтингу У @SooRэто показано raiting можно считать / пресчитывать при появлении, изменении комментария - создав или отдельную таблицу или отдельное поле Если включена статистика, то возможно менять myisam на inodb для исключения блокировок Или выносить в отдельную таблицу Надіслати Поділитися на інших сайтах More sharing options... 100napb Опубліковано: 20 жовтня 2019 Автор Share Опубліковано: 20 жовтня 2019 (змінено) 9 minutes ago, chukcha said: discount и special нельзя выносить из подзапроса 9 minutes ago, chukcha said: сделайте две одинаковых записи, или пересечение дат отсюда нельзя? Spoiler можно. тут получается нечто вроде цикла: для каждого значения\строки p.product_id, которое передается в этот подзоапрос будет вычисляться price. мой вариант не делает зависимого запроса (заменен джоином) и возвращает в точности тот же набор данных, что и нативный. Змінено 20 жовтня 2019 користувачем 100napb Надіслати Поділитися на інших сайтах More sharing options... 100napb Опубліковано: 20 жовтня 2019 Автор Share Опубліковано: 20 жовтня 2019 29 minutes ago, chukcha said: raiting можно считать / пресчитывать при появлении, изменении комментария - создав или отдельную таблицу или отдельное поле можно заморочиться. да. но стоит ли оно того? вроде затраты копеечные. даже если отзывов на проекте будет пару тысяч, думаю, картина не сильно изменится Spoiler Надіслати Поділитися на інших сайтах More sharing options... chukcha Опубліковано: 20 жовтня 2019 Share Опубліковано: 20 жовтня 2019 16 минут назад, 100napb сказал: но стоит ли оно того? Для одиночного запроса - несущественно Надіслати Поділитися на інших сайтах More sharing options... chukcha Опубліковано: 20 жовтня 2019 Share Опубліковано: 20 жовтня 2019 SELECT price FROM oc_product_discount pd2 WHERE pd2.product_id = p.product_id AND pd2.customer_group_id = '1' AND pd2.quantity = '1' AND ((pd2.date_start = '0000-00-00' OR pd2.date_start < NOW()) AND (pd2.date_end = '0000-00-00' OR pd2.date_end > NOW())) ORDER BY pd2.priority ASC, pd2.price ASC LIMIT 1 Сколько вернет записей? при Date_start:0000-00-00 Date_end:0000-00000 priority:1 и Date_start:2019-01-01 Date_end:2019-12-31 priority:0 А сколько SELECT * FROM oc_product p LEFT JOIN oc_product_discount pd2 ON (p.product_id = pd2.product_id ON (pd2.product_id = p.product_id AND pd2.customer_group_id = '1' AND pd2.quantity = '1' AND ((pd2.date_start = '0000-00-00' OR pd2.date_start < NOW()) AND (pd2.date_end = '0000-00-00' OR pd2.date_end > NOW()))) Для одного товара при пресечении дат? 1 Надіслати Поділитися на інших сайтах More sharing options... 100napb Опубліковано: 20 жовтня 2019 Автор Share Опубліковано: 20 жовтня 2019 (змінено) 2 hours ago, chukcha said: . понял о чем Вы. Респект за внимательность. Действительно, предложенный выше вариант не учитывал случая наличия конкурентных скидок или акций и не мог однозначно определить приоритетную (итоговую) цену. Виноват. Проглядел. Редкий кейс. Но запрос легко исправляется без каких-либо потерей в скорости (проверил). В спойлер ниже закинул и выделил цветом строки, которые решают этот недочет. Spoiler SELECT SQL_NO_CACHE p.product_id, rating.total AS rating, MIN(pd2.price) AS discount, MIN(ps.price) AS special FROM oc_product_to_category p2c 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) LEFT JOIN oc_product_special ps ON (p.product_id = ps.product_id AND ps.priority = (SELECT MIN(priority) FROM oc_product_special WHERE product_id = p.product_id AND customer_group_id = '1' AND ((date_start = '0000-00-00' OR date_start < NOW()) AND (date_end = '0000-00-00' OR date_end > NOW()))) AND customer_group_id = '1' AND ((ps.date_start = '0000-00-00' OR ps.date_start < NOW()) AND (ps.date_end = '0000-00-00' OR ps.date_end > NOW()))) LEFT JOIN oc_product_discount pd2 ON (pd2.product_id = p.product_id AND ps.priority = (SELECT MIN(priority) FROM oc_product_discount WHERE product_id = p.product_id AND customer_group_id = '1' AND ((date_start = '0000-00-00' OR date_start < NOW()) AND (date_end = '0000-00-00' OR date_end > NOW()))) AND pd2.customer_group_id = '1' AND pd2.quantity = '1' AND ((pd2.date_start = '0000-00-00' OR pd2.date_start < NOW()) AND (pd2.date_end = '0000-00-00' OR pd2.date_end > NOW()))) LEFT JOIN (SELECT AVG(rating) AS total, r1.product_id FROM oc_review r1 WHERE r1.status = '1' GROUP BY r1.product_id) AS rating ON p.product_id = rating.product_id WHERE pd.language_id = '1' AND p.status = '1' AND p.date_available <= NOW() AND p2s.store_id = '0' -- AND p2c.category_id = '37' GROUP BY p.product_id ORDER BY p.sort_order ASC, LCASE(pd.name) ASC LIMIT 0, 12 Змінено 20 жовтня 2019 користувачем 100napb Надіслати Поділитися на інших сайтах More sharing options... chukcha Опубліковано: 20 жовтня 2019 Share Опубліковано: 20 жовтня 2019 Я вам поведаю тайну что min и max не очень шустрые.. Все равно в getProduct эти подзапросы существуют А вот тут-то .. не хочу утверждать.. Не проверял, не знаю, но по оракл-опыту getProducts 1.SELECT *, sub_query getProduct 2.SELECT *, sub_query то если код sub_query одинаков до символа, то он будет закеширован и представлен в байткод на момент сессии коннекта. Надіслати Поділитися на інших сайтах More sharing options... 100napb Опубліковано: 20 жовтня 2019 Автор Share Опубліковано: 20 жовтня 2019 (змінено) 18 minutes ago, chukcha said: что min и max не очень шустрые.. все относительно. 1) тут им предстоит определить минимум для небольшого набора значений. очень небольшого 2) я действительно перепроверил результаты из стартового поста. Они актуальные с обновленным запросом Spoiler нативный запрос модифицированный запрос активный товар - этот тот, у которого p.status = 1, т.е. включенная карточка для 100 активных товаров: ~ 0.04сек; (0.04сек) для 6к активных товаров: ~0.4сек (0.2сек) для 19к активных товаров: ~ 2.1сек (0.6сек) для 33к активных товаров: ~2.3сек (1.3сек) для 100к активных товаров: ~7.1 сек (1.5сек) 18 minutes ago, chukcha said: то если код sub_query одинаков до символа, то он будет закеширован и представлен в байткод на момент сессии коннекта. тут, в мускуле\марии, проще и такой проблемы не случится. кэширование подзапросов действует только в рамках одного родительского запроса. на другие не распространяется. За эту оптимизацию отвечает параметр optimizer_switch='subquery_cache=OFF'. Гуглится легко. Строго говоря, мысль была простая: уйти от дорогих зависимых подзапросов в сторону более оптимизированных джоинов. И пока, вроде как, идея жизнеспособна ) Спасибо за замечания. Змінено 20 жовтня 2019 користувачем 100napb погуглил сам))) кажется, кэширование подзапросов - это фича только mariadb Надіслати Поділитися на інших сайтах More sharing options... 1 month later... 100napb Опубліковано: 16 грудня 2019 Автор Share Опубліковано: 16 грудня 2019 Уважаемые, а есть у кого-нибудь опыт\результаты по скорости выполнения запроса из getProducts, если основным хранилищем данных для него будет Sphinx, а не mysql ? А то я тут еще ускорил и стало интересно, а насколько сфинкс круче. Если не сложно, укажите исходное количество товаров для выборки(товаров в категории) и время получения результата с хотя бы "нативной" сортировкой по sort_order и name Надіслати Поділитися на інших сайтах More sharing options... Yoda Опубліковано: 17 грудня 2019 Share Опубліковано: 17 грудня 2019 В 16.12.2019 в 09:16, 100napb сказал: Уважаемые, а есть у кого-нибудь опыт\результаты по скорости выполнения запроса из getProducts, если основным хранилищем данных для него будет Sphinx, а не mysql ? А то я тут еще ускорил и стало интересно, а насколько сфинкс круче. Если не сложно, укажите исходное количество товаров для выборки(товаров в категории) и время получения результата с хотя бы "нативной" сортировкой по sort_order и name mysql> SELECT COUNT(*) as qty FROM product; +---------+ | qty | +---------+ | 1871817 | +---------+ 1 row in set (0.02 sec) mysql> SELECT id FROM main ORDER BY name DESC; +---------+ | id | +---------+ | 5989213 | | 6091563 | | 4350213 | | 4350196 | | 4350195 | | 4350197 | | 4350194 | | 4350192 | | 4350191 | | 4350193 | | 4350190 | | 4350217 | | 4350216 | | 5827378 | | 5827377 | | 5827376 | | 5827375 | | 5827374 | | 5827373 | | 5827372 | +---------+ 20 rows in set (0.16 sec) Но у вас так не получится! Сфинкс не всем раскрывает свои загадки! 2 Надіслати Поділитися на інших сайтах More sharing options... 100napb Опубліковано: 17 грудня 2019 Автор Share Опубліковано: 17 грудня 2019 3 hours ago, Yoda said: Но у вас так не получится! Сфинкс не всем раскрывает свои загадки! Спасибо большое за отклик и пример. Больше всего надеялся именно на Ваш ответ. Spoiler к сожалению а) у меня нет под рукой базы с таким количество реальных товаров. Но ради быстрого теста размножил имеющиеся, сохранив необходимую уникальность. б) аналогично Вашему примеру упростим запрос SELECT SQL_NO_CACHE COUNT(*) AS qty FROM product_; Запрос открыт за 0,039c [0,031c выполнение, 0,008c выборка] 1 строк выбрано qty --------------------- 2518592 SELECT SQL_NO_CACHE p.product_id FROM product_ p ORDER BY p.sort_order, p.name LIMIT 0,60; Запрос открыт за 0,048c [0,034c выполнение, 0,014c выборка] 60 строк выбрано product_id ----------- 3797248 3797247 3796136 ... без сфинкса, коробочная мариядб, даже не самая последняя. 1 Надіслати Поділитися на інших сайтах More sharing options... Yoda Опубліковано: 17 грудня 2019 Share Опубліковано: 17 грудня 2019 16 минут назад, 100napb сказал: Спасибо большое за отклик и пример. Больше всего надеялся именно на Ваш ответ. Показать контент к сожалению а) у меня нет под рукой базы с таким количество реальных товаров. Но ради быстрого теста размножил имеющиеся, сохранив необходимую уникальность. б) аналогично Вашему примеру упростим запрос SELECT SQL_NO_CACHE COUNT(*) AS qty FROM product_; Запрос открыт за 0,039c [0,031c выполнение, 0,008c выборка] 1 строк выбрано qty --------------------- 2518592 SELECT SQL_NO_CACHE p.product_id FROM product_ p ORDER BY p.sort_order, p.name LIMIT 0,60; Запрос открыт за 0,048c [0,034c выполнение, 0,014c выборка] 60 строк выбрано product_id ----------- 3797248 3797247 3796136 ... без сфинкса, коробочная мариядб, даже не самая последняя. А толку от него. sql запросы ограничены, просто взять и взять пихнуть в индекс базу не выйдет. Конфликтов с любым дополнением не оберешься. Любой фильтр в целом на категории до 5к товаров настраивается и с mysql базой. Как и любой магазин до 200-300к. Менять архитектуру хранилища, жертвуя совместимостью имеет смысл только в очень специфических случаях, когда вы будете уверены, что в любой момент сможете помочь клиенту со сторонними расширенями. Проблемы с индексацией начинаются где-то с 100к товаров, и зачастую их решение - это какие то не то что костыли а КОСТЫЛЮГИ! Чтобы подружить любой фильтр - надо как минимум написать самому фильтр. Поэтому там где не надо 50к товаров в одной категории, разворачивать сфинкс под каталог - это просто садить на иглу потенциального заказчика. Намного утилитарней, проще и эффективнее, сделать сводные таблицы (исключив лишние джоины) и расставить правильный порядок таблиц в запросе, как в фильтре у маэстро @SooR, так как в итоге это решение, в котором может разобраться любой разработчик. 2 Надіслати Поділитися на інших сайтах More sharing options... Створіть аккаунт або увійдіть для коментування Ви повинні бути користувачем, щоб залишити коментар Створити обліковий запис Зареєструйтеся для отримання облікового запису. Це просто! Зареєструвати аккаунт Вхід Уже зареєстровані? Увійдіть тут. Вхід зараз Share More sharing options... Передплатники 0 Перейти до списку тем Зараз на сторінці 0 користувачів Ні користувачів, які переглядиють цю сторінку Последние темы Последние дополнения Последние новости Вся активність Головна Разное Курилка ускорить sql-запрос из getProducts в /catalog/model/catalog/product.php Покупцям Оплата розширень фізичними особами Оплата розширень юридичними особами Політика повернень Розробникам Регламент розміщення розширень Регламент продажу та підтримки розширень Віртуальний обліковий запис автора Політика просування оголошень API каталогу розширень Вирішення спорів щодо авторських прав Корисна інформація Публічна оферта Політика повернень Політика конфіденційності Платіжна політика Політика передачі особистих даних Політика прозорості Останні розширення PRICE MASTER - Модуль імпорту/експорту товарів, парсинг, переклад, генерація текстів, редактор каталогу та багато іншого Автор: ScriptBrains 1.0 Синхронізація Замовлень Rozetka.ua та Opencart Автор: sinco Product Manipulator Автор: Hiperlynx007 Видалення дублікатів товарів для OpenCart Автор: Hatshypsut Вибір категорій і виробників для "Знайшли дешевше" шаблону Upstore Автор: Flint2000 × Уже зареєстровані? Ввійти Реєстрація Ваші замовлення Назад Придбані модулі та шаблони Ваші рахунки Лист очікувань Альтернативні контакти Форум Новини ocStore Назад Офіційний сайт Демо ocStore 3.0.3.2 Демо ocStore 2.3.0.2.4 Завантажити ocStore Документація Історія версій ocStore Блоги Модулі Шаблони Назад Безкоштовні шаблони Платні шаблони Де купувати модулі? Послуги FAQ OpenCart.Pro Назад Демо Купити Порівняння × Створити... Important Information На нашому сайті використовуються файли cookie і відбувається обробка деяких персональних даних користувачів, щоб поліпшити користувальницький інтерфейс. Щоб дізнатися для чого і які персональні дані ми обробляємо перейдіть за посиланням . Якщо Ви натиснете «Я даю згоду», це означає, що Ви розумієте і приймаєте всі умови, зазначені в цьому Повідомленні про конфіденційність. Я даю згоду
100napb Опубліковано: 20 жовтня 2019 Автор Share Опубліковано: 20 жовтня 2019 26 minutes ago, SooR said: Как по мне, то эти join'ы нужно добавлять по требованию. Согласен. Есть нужный запрос\требование к результата функции во входящем $data - логично джоинить нужные блоки, будь-то акции, рейтинг, регулярная цена или что-то иное. Тем более, эти дополнительные вычисления однозначно требуют значительных ресурсов и времени. Тем более, что даже в нативной структуре блоки вычислений вполне себе обособлены и находится в select-секции запрашиваемых переменных в качестве связанных подзапросов (DEPENDENT SUBQUERY, что не шибко быстро). Но главное обособлены. И их, в принципе, не трудно подключать\отключать. Например как в Вашем примере. *тумбс_ап* 44 minutes ago, SooR said: Также рассматриваю варианты замены связей product_to_category на статичное поле category_id в таблице product. эм... а зачем? потеряется нормализация данных, например, в том случае, если товар в нескольких категориях. тем более джоинить ряд мелких таблиц типа product_to_category и накладывать в них дополнительные ограничения-условия на данные в where секции очень дешево, а если есть все нужные индексы - так и вообще... спасибо за отклик. Надіслати Поділитися на інших сайтах More sharing options... chukcha Опубліковано: 20 жовтня 2019 Share Опубліковано: 20 жовтня 2019 discount и special нельзя выносить из подзапроса сделайте две одинаковых записи, или пересечение дат discount и специал нужны толко при сортировке по цене rating - при сортировке по рейтингу У @SooRэто показано raiting можно считать / пресчитывать при появлении, изменении комментария - создав или отдельную таблицу или отдельное поле Если включена статистика, то возможно менять myisam на inodb для исключения блокировок Или выносить в отдельную таблицу Надіслати Поділитися на інших сайтах More sharing options... 100napb Опубліковано: 20 жовтня 2019 Автор Share Опубліковано: 20 жовтня 2019 (змінено) 9 minutes ago, chukcha said: discount и special нельзя выносить из подзапроса 9 minutes ago, chukcha said: сделайте две одинаковых записи, или пересечение дат отсюда нельзя? Spoiler можно. тут получается нечто вроде цикла: для каждого значения\строки p.product_id, которое передается в этот подзоапрос будет вычисляться price. мой вариант не делает зависимого запроса (заменен джоином) и возвращает в точности тот же набор данных, что и нативный. Змінено 20 жовтня 2019 користувачем 100napb Надіслати Поділитися на інших сайтах More sharing options... 100napb Опубліковано: 20 жовтня 2019 Автор Share Опубліковано: 20 жовтня 2019 29 minutes ago, chukcha said: raiting можно считать / пресчитывать при появлении, изменении комментария - создав или отдельную таблицу или отдельное поле можно заморочиться. да. но стоит ли оно того? вроде затраты копеечные. даже если отзывов на проекте будет пару тысяч, думаю, картина не сильно изменится Spoiler Надіслати Поділитися на інших сайтах More sharing options... chukcha Опубліковано: 20 жовтня 2019 Share Опубліковано: 20 жовтня 2019 16 минут назад, 100napb сказал: но стоит ли оно того? Для одиночного запроса - несущественно Надіслати Поділитися на інших сайтах More sharing options... chukcha Опубліковано: 20 жовтня 2019 Share Опубліковано: 20 жовтня 2019 SELECT price FROM oc_product_discount pd2 WHERE pd2.product_id = p.product_id AND pd2.customer_group_id = '1' AND pd2.quantity = '1' AND ((pd2.date_start = '0000-00-00' OR pd2.date_start < NOW()) AND (pd2.date_end = '0000-00-00' OR pd2.date_end > NOW())) ORDER BY pd2.priority ASC, pd2.price ASC LIMIT 1 Сколько вернет записей? при Date_start:0000-00-00 Date_end:0000-00000 priority:1 и Date_start:2019-01-01 Date_end:2019-12-31 priority:0 А сколько SELECT * FROM oc_product p LEFT JOIN oc_product_discount pd2 ON (p.product_id = pd2.product_id ON (pd2.product_id = p.product_id AND pd2.customer_group_id = '1' AND pd2.quantity = '1' AND ((pd2.date_start = '0000-00-00' OR pd2.date_start < NOW()) AND (pd2.date_end = '0000-00-00' OR pd2.date_end > NOW()))) Для одного товара при пресечении дат? 1 Надіслати Поділитися на інших сайтах More sharing options... 100napb Опубліковано: 20 жовтня 2019 Автор Share Опубліковано: 20 жовтня 2019 (змінено) 2 hours ago, chukcha said: . понял о чем Вы. Респект за внимательность. Действительно, предложенный выше вариант не учитывал случая наличия конкурентных скидок или акций и не мог однозначно определить приоритетную (итоговую) цену. Виноват. Проглядел. Редкий кейс. Но запрос легко исправляется без каких-либо потерей в скорости (проверил). В спойлер ниже закинул и выделил цветом строки, которые решают этот недочет. Spoiler SELECT SQL_NO_CACHE p.product_id, rating.total AS rating, MIN(pd2.price) AS discount, MIN(ps.price) AS special FROM oc_product_to_category p2c 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) LEFT JOIN oc_product_special ps ON (p.product_id = ps.product_id AND ps.priority = (SELECT MIN(priority) FROM oc_product_special WHERE product_id = p.product_id AND customer_group_id = '1' AND ((date_start = '0000-00-00' OR date_start < NOW()) AND (date_end = '0000-00-00' OR date_end > NOW()))) AND customer_group_id = '1' AND ((ps.date_start = '0000-00-00' OR ps.date_start < NOW()) AND (ps.date_end = '0000-00-00' OR ps.date_end > NOW()))) LEFT JOIN oc_product_discount pd2 ON (pd2.product_id = p.product_id AND ps.priority = (SELECT MIN(priority) FROM oc_product_discount WHERE product_id = p.product_id AND customer_group_id = '1' AND ((date_start = '0000-00-00' OR date_start < NOW()) AND (date_end = '0000-00-00' OR date_end > NOW()))) AND pd2.customer_group_id = '1' AND pd2.quantity = '1' AND ((pd2.date_start = '0000-00-00' OR pd2.date_start < NOW()) AND (pd2.date_end = '0000-00-00' OR pd2.date_end > NOW()))) LEFT JOIN (SELECT AVG(rating) AS total, r1.product_id FROM oc_review r1 WHERE r1.status = '1' GROUP BY r1.product_id) AS rating ON p.product_id = rating.product_id WHERE pd.language_id = '1' AND p.status = '1' AND p.date_available <= NOW() AND p2s.store_id = '0' -- AND p2c.category_id = '37' GROUP BY p.product_id ORDER BY p.sort_order ASC, LCASE(pd.name) ASC LIMIT 0, 12 Змінено 20 жовтня 2019 користувачем 100napb Надіслати Поділитися на інших сайтах More sharing options... chukcha Опубліковано: 20 жовтня 2019 Share Опубліковано: 20 жовтня 2019 Я вам поведаю тайну что min и max не очень шустрые.. Все равно в getProduct эти подзапросы существуют А вот тут-то .. не хочу утверждать.. Не проверял, не знаю, но по оракл-опыту getProducts 1.SELECT *, sub_query getProduct 2.SELECT *, sub_query то если код sub_query одинаков до символа, то он будет закеширован и представлен в байткод на момент сессии коннекта. Надіслати Поділитися на інших сайтах More sharing options... 100napb Опубліковано: 20 жовтня 2019 Автор Share Опубліковано: 20 жовтня 2019 (змінено) 18 minutes ago, chukcha said: что min и max не очень шустрые.. все относительно. 1) тут им предстоит определить минимум для небольшого набора значений. очень небольшого 2) я действительно перепроверил результаты из стартового поста. Они актуальные с обновленным запросом Spoiler нативный запрос модифицированный запрос активный товар - этот тот, у которого p.status = 1, т.е. включенная карточка для 100 активных товаров: ~ 0.04сек; (0.04сек) для 6к активных товаров: ~0.4сек (0.2сек) для 19к активных товаров: ~ 2.1сек (0.6сек) для 33к активных товаров: ~2.3сек (1.3сек) для 100к активных товаров: ~7.1 сек (1.5сек) 18 minutes ago, chukcha said: то если код sub_query одинаков до символа, то он будет закеширован и представлен в байткод на момент сессии коннекта. тут, в мускуле\марии, проще и такой проблемы не случится. кэширование подзапросов действует только в рамках одного родительского запроса. на другие не распространяется. За эту оптимизацию отвечает параметр optimizer_switch='subquery_cache=OFF'. Гуглится легко. Строго говоря, мысль была простая: уйти от дорогих зависимых подзапросов в сторону более оптимизированных джоинов. И пока, вроде как, идея жизнеспособна ) Спасибо за замечания. Змінено 20 жовтня 2019 користувачем 100napb погуглил сам))) кажется, кэширование подзапросов - это фича только mariadb Надіслати Поділитися на інших сайтах More sharing options... 1 month later... 100napb Опубліковано: 16 грудня 2019 Автор Share Опубліковано: 16 грудня 2019 Уважаемые, а есть у кого-нибудь опыт\результаты по скорости выполнения запроса из getProducts, если основным хранилищем данных для него будет Sphinx, а не mysql ? А то я тут еще ускорил и стало интересно, а насколько сфинкс круче. Если не сложно, укажите исходное количество товаров для выборки(товаров в категории) и время получения результата с хотя бы "нативной" сортировкой по sort_order и name Надіслати Поділитися на інших сайтах More sharing options... Yoda Опубліковано: 17 грудня 2019 Share Опубліковано: 17 грудня 2019 В 16.12.2019 в 09:16, 100napb сказал: Уважаемые, а есть у кого-нибудь опыт\результаты по скорости выполнения запроса из getProducts, если основным хранилищем данных для него будет Sphinx, а не mysql ? А то я тут еще ускорил и стало интересно, а насколько сфинкс круче. Если не сложно, укажите исходное количество товаров для выборки(товаров в категории) и время получения результата с хотя бы "нативной" сортировкой по sort_order и name mysql> SELECT COUNT(*) as qty FROM product; +---------+ | qty | +---------+ | 1871817 | +---------+ 1 row in set (0.02 sec) mysql> SELECT id FROM main ORDER BY name DESC; +---------+ | id | +---------+ | 5989213 | | 6091563 | | 4350213 | | 4350196 | | 4350195 | | 4350197 | | 4350194 | | 4350192 | | 4350191 | | 4350193 | | 4350190 | | 4350217 | | 4350216 | | 5827378 | | 5827377 | | 5827376 | | 5827375 | | 5827374 | | 5827373 | | 5827372 | +---------+ 20 rows in set (0.16 sec) Но у вас так не получится! Сфинкс не всем раскрывает свои загадки! 2 Надіслати Поділитися на інших сайтах More sharing options... 100napb Опубліковано: 17 грудня 2019 Автор Share Опубліковано: 17 грудня 2019 3 hours ago, Yoda said: Но у вас так не получится! Сфинкс не всем раскрывает свои загадки! Спасибо большое за отклик и пример. Больше всего надеялся именно на Ваш ответ. Spoiler к сожалению а) у меня нет под рукой базы с таким количество реальных товаров. Но ради быстрого теста размножил имеющиеся, сохранив необходимую уникальность. б) аналогично Вашему примеру упростим запрос SELECT SQL_NO_CACHE COUNT(*) AS qty FROM product_; Запрос открыт за 0,039c [0,031c выполнение, 0,008c выборка] 1 строк выбрано qty --------------------- 2518592 SELECT SQL_NO_CACHE p.product_id FROM product_ p ORDER BY p.sort_order, p.name LIMIT 0,60; Запрос открыт за 0,048c [0,034c выполнение, 0,014c выборка] 60 строк выбрано product_id ----------- 3797248 3797247 3796136 ... без сфинкса, коробочная мариядб, даже не самая последняя. 1 Надіслати Поділитися на інших сайтах More sharing options... Yoda Опубліковано: 17 грудня 2019 Share Опубліковано: 17 грудня 2019 16 минут назад, 100napb сказал: Спасибо большое за отклик и пример. Больше всего надеялся именно на Ваш ответ. Показать контент к сожалению а) у меня нет под рукой базы с таким количество реальных товаров. Но ради быстрого теста размножил имеющиеся, сохранив необходимую уникальность. б) аналогично Вашему примеру упростим запрос SELECT SQL_NO_CACHE COUNT(*) AS qty FROM product_; Запрос открыт за 0,039c [0,031c выполнение, 0,008c выборка] 1 строк выбрано qty --------------------- 2518592 SELECT SQL_NO_CACHE p.product_id FROM product_ p ORDER BY p.sort_order, p.name LIMIT 0,60; Запрос открыт за 0,048c [0,034c выполнение, 0,014c выборка] 60 строк выбрано product_id ----------- 3797248 3797247 3796136 ... без сфинкса, коробочная мариядб, даже не самая последняя. А толку от него. sql запросы ограничены, просто взять и взять пихнуть в индекс базу не выйдет. Конфликтов с любым дополнением не оберешься. Любой фильтр в целом на категории до 5к товаров настраивается и с mysql базой. Как и любой магазин до 200-300к. Менять архитектуру хранилища, жертвуя совместимостью имеет смысл только в очень специфических случаях, когда вы будете уверены, что в любой момент сможете помочь клиенту со сторонними расширенями. Проблемы с индексацией начинаются где-то с 100к товаров, и зачастую их решение - это какие то не то что костыли а КОСТЫЛЮГИ! Чтобы подружить любой фильтр - надо как минимум написать самому фильтр. Поэтому там где не надо 50к товаров в одной категории, разворачивать сфинкс под каталог - это просто садить на иглу потенциального заказчика. Намного утилитарней, проще и эффективнее, сделать сводные таблицы (исключив лишние джоины) и расставить правильный порядок таблиц в запросе, как в фильтре у маэстро @SooR, так как в итоге это решение, в котором может разобраться любой разработчик. 2 Надіслати Поділитися на інших сайтах More sharing options... Створіть аккаунт або увійдіть для коментування Ви повинні бути користувачем, щоб залишити коментар Створити обліковий запис Зареєструйтеся для отримання облікового запису. Це просто! Зареєструвати аккаунт Вхід Уже зареєстровані? Увійдіть тут. Вхід зараз Share More sharing options... Передплатники 0 Перейти до списку тем Зараз на сторінці 0 користувачів Ні користувачів, які переглядиють цю сторінку Последние темы Последние дополнения Последние новости Вся активність Головна Разное Курилка ускорить sql-запрос из getProducts в /catalog/model/catalog/product.php Покупцям Оплата розширень фізичними особами Оплата розширень юридичними особами Політика повернень Розробникам Регламент розміщення розширень Регламент продажу та підтримки розширень Віртуальний обліковий запис автора Політика просування оголошень API каталогу розширень Вирішення спорів щодо авторських прав Корисна інформація Публічна оферта Політика повернень Політика конфіденційності Платіжна політика Політика передачі особистих даних Політика прозорості Останні розширення PRICE MASTER - Модуль імпорту/експорту товарів, парсинг, переклад, генерація текстів, редактор каталогу та багато іншого Автор: ScriptBrains 1.0 Синхронізація Замовлень Rozetka.ua та Opencart Автор: sinco Product Manipulator Автор: Hiperlynx007 Видалення дублікатів товарів для OpenCart Автор: Hatshypsut Вибір категорій і виробників для "Знайшли дешевше" шаблону Upstore Автор: Flint2000 × Уже зареєстровані? Ввійти Реєстрація Ваші замовлення Назад Придбані модулі та шаблони Ваші рахунки Лист очікувань Альтернативні контакти Форум Новини ocStore Назад Офіційний сайт Демо ocStore 3.0.3.2 Демо ocStore 2.3.0.2.4 Завантажити ocStore Документація Історія версій ocStore Блоги Модулі Шаблони Назад Безкоштовні шаблони Платні шаблони Де купувати модулі? Послуги FAQ OpenCart.Pro Назад Демо Купити Порівняння × Створити... Important Information На нашому сайті використовуються файли cookie і відбувається обробка деяких персональних даних користувачів, щоб поліпшити користувальницький інтерфейс. Щоб дізнатися для чого і які персональні дані ми обробляємо перейдіть за посиланням . Якщо Ви натиснете «Я даю згоду», це означає, що Ви розумієте і приймаєте всі умови, зазначені в цьому Повідомленні про конфіденційність. Я даю згоду
chukcha Опубліковано: 20 жовтня 2019 Share Опубліковано: 20 жовтня 2019 discount и special нельзя выносить из подзапроса сделайте две одинаковых записи, или пересечение дат discount и специал нужны толко при сортировке по цене rating - при сортировке по рейтингу У @SooRэто показано raiting можно считать / пресчитывать при появлении, изменении комментария - создав или отдельную таблицу или отдельное поле Если включена статистика, то возможно менять myisam на inodb для исключения блокировок Или выносить в отдельную таблицу Надіслати Поділитися на інших сайтах More sharing options... 100napb Опубліковано: 20 жовтня 2019 Автор Share Опубліковано: 20 жовтня 2019 (змінено) 9 minutes ago, chukcha said: discount и special нельзя выносить из подзапроса 9 minutes ago, chukcha said: сделайте две одинаковых записи, или пересечение дат отсюда нельзя? Spoiler можно. тут получается нечто вроде цикла: для каждого значения\строки p.product_id, которое передается в этот подзоапрос будет вычисляться price. мой вариант не делает зависимого запроса (заменен джоином) и возвращает в точности тот же набор данных, что и нативный. Змінено 20 жовтня 2019 користувачем 100napb Надіслати Поділитися на інших сайтах More sharing options... 100napb Опубліковано: 20 жовтня 2019 Автор Share Опубліковано: 20 жовтня 2019 29 minutes ago, chukcha said: raiting можно считать / пресчитывать при появлении, изменении комментария - создав или отдельную таблицу или отдельное поле можно заморочиться. да. но стоит ли оно того? вроде затраты копеечные. даже если отзывов на проекте будет пару тысяч, думаю, картина не сильно изменится Spoiler Надіслати Поділитися на інших сайтах More sharing options... chukcha Опубліковано: 20 жовтня 2019 Share Опубліковано: 20 жовтня 2019 16 минут назад, 100napb сказал: но стоит ли оно того? Для одиночного запроса - несущественно Надіслати Поділитися на інших сайтах More sharing options... chukcha Опубліковано: 20 жовтня 2019 Share Опубліковано: 20 жовтня 2019 SELECT price FROM oc_product_discount pd2 WHERE pd2.product_id = p.product_id AND pd2.customer_group_id = '1' AND pd2.quantity = '1' AND ((pd2.date_start = '0000-00-00' OR pd2.date_start < NOW()) AND (pd2.date_end = '0000-00-00' OR pd2.date_end > NOW())) ORDER BY pd2.priority ASC, pd2.price ASC LIMIT 1 Сколько вернет записей? при Date_start:0000-00-00 Date_end:0000-00000 priority:1 и Date_start:2019-01-01 Date_end:2019-12-31 priority:0 А сколько SELECT * FROM oc_product p LEFT JOIN oc_product_discount pd2 ON (p.product_id = pd2.product_id ON (pd2.product_id = p.product_id AND pd2.customer_group_id = '1' AND pd2.quantity = '1' AND ((pd2.date_start = '0000-00-00' OR pd2.date_start < NOW()) AND (pd2.date_end = '0000-00-00' OR pd2.date_end > NOW()))) Для одного товара при пресечении дат? 1 Надіслати Поділитися на інших сайтах More sharing options... 100napb Опубліковано: 20 жовтня 2019 Автор Share Опубліковано: 20 жовтня 2019 (змінено) 2 hours ago, chukcha said: . понял о чем Вы. Респект за внимательность. Действительно, предложенный выше вариант не учитывал случая наличия конкурентных скидок или акций и не мог однозначно определить приоритетную (итоговую) цену. Виноват. Проглядел. Редкий кейс. Но запрос легко исправляется без каких-либо потерей в скорости (проверил). В спойлер ниже закинул и выделил цветом строки, которые решают этот недочет. Spoiler SELECT SQL_NO_CACHE p.product_id, rating.total AS rating, MIN(pd2.price) AS discount, MIN(ps.price) AS special FROM oc_product_to_category p2c 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) LEFT JOIN oc_product_special ps ON (p.product_id = ps.product_id AND ps.priority = (SELECT MIN(priority) FROM oc_product_special WHERE product_id = p.product_id AND customer_group_id = '1' AND ((date_start = '0000-00-00' OR date_start < NOW()) AND (date_end = '0000-00-00' OR date_end > NOW()))) AND customer_group_id = '1' AND ((ps.date_start = '0000-00-00' OR ps.date_start < NOW()) AND (ps.date_end = '0000-00-00' OR ps.date_end > NOW()))) LEFT JOIN oc_product_discount pd2 ON (pd2.product_id = p.product_id AND ps.priority = (SELECT MIN(priority) FROM oc_product_discount WHERE product_id = p.product_id AND customer_group_id = '1' AND ((date_start = '0000-00-00' OR date_start < NOW()) AND (date_end = '0000-00-00' OR date_end > NOW()))) AND pd2.customer_group_id = '1' AND pd2.quantity = '1' AND ((pd2.date_start = '0000-00-00' OR pd2.date_start < NOW()) AND (pd2.date_end = '0000-00-00' OR pd2.date_end > NOW()))) LEFT JOIN (SELECT AVG(rating) AS total, r1.product_id FROM oc_review r1 WHERE r1.status = '1' GROUP BY r1.product_id) AS rating ON p.product_id = rating.product_id WHERE pd.language_id = '1' AND p.status = '1' AND p.date_available <= NOW() AND p2s.store_id = '0' -- AND p2c.category_id = '37' GROUP BY p.product_id ORDER BY p.sort_order ASC, LCASE(pd.name) ASC LIMIT 0, 12 Змінено 20 жовтня 2019 користувачем 100napb Надіслати Поділитися на інших сайтах More sharing options... chukcha Опубліковано: 20 жовтня 2019 Share Опубліковано: 20 жовтня 2019 Я вам поведаю тайну что min и max не очень шустрые.. Все равно в getProduct эти подзапросы существуют А вот тут-то .. не хочу утверждать.. Не проверял, не знаю, но по оракл-опыту getProducts 1.SELECT *, sub_query getProduct 2.SELECT *, sub_query то если код sub_query одинаков до символа, то он будет закеширован и представлен в байткод на момент сессии коннекта. Надіслати Поділитися на інших сайтах More sharing options... 100napb Опубліковано: 20 жовтня 2019 Автор Share Опубліковано: 20 жовтня 2019 (змінено) 18 minutes ago, chukcha said: что min и max не очень шустрые.. все относительно. 1) тут им предстоит определить минимум для небольшого набора значений. очень небольшого 2) я действительно перепроверил результаты из стартового поста. Они актуальные с обновленным запросом Spoiler нативный запрос модифицированный запрос активный товар - этот тот, у которого p.status = 1, т.е. включенная карточка для 100 активных товаров: ~ 0.04сек; (0.04сек) для 6к активных товаров: ~0.4сек (0.2сек) для 19к активных товаров: ~ 2.1сек (0.6сек) для 33к активных товаров: ~2.3сек (1.3сек) для 100к активных товаров: ~7.1 сек (1.5сек) 18 minutes ago, chukcha said: то если код sub_query одинаков до символа, то он будет закеширован и представлен в байткод на момент сессии коннекта. тут, в мускуле\марии, проще и такой проблемы не случится. кэширование подзапросов действует только в рамках одного родительского запроса. на другие не распространяется. За эту оптимизацию отвечает параметр optimizer_switch='subquery_cache=OFF'. Гуглится легко. Строго говоря, мысль была простая: уйти от дорогих зависимых подзапросов в сторону более оптимизированных джоинов. И пока, вроде как, идея жизнеспособна ) Спасибо за замечания. Змінено 20 жовтня 2019 користувачем 100napb погуглил сам))) кажется, кэширование подзапросов - это фича только mariadb Надіслати Поділитися на інших сайтах More sharing options... 1 month later... 100napb Опубліковано: 16 грудня 2019 Автор Share Опубліковано: 16 грудня 2019 Уважаемые, а есть у кого-нибудь опыт\результаты по скорости выполнения запроса из getProducts, если основным хранилищем данных для него будет Sphinx, а не mysql ? А то я тут еще ускорил и стало интересно, а насколько сфинкс круче. Если не сложно, укажите исходное количество товаров для выборки(товаров в категории) и время получения результата с хотя бы "нативной" сортировкой по sort_order и name Надіслати Поділитися на інших сайтах More sharing options... Yoda Опубліковано: 17 грудня 2019 Share Опубліковано: 17 грудня 2019 В 16.12.2019 в 09:16, 100napb сказал: Уважаемые, а есть у кого-нибудь опыт\результаты по скорости выполнения запроса из getProducts, если основным хранилищем данных для него будет Sphinx, а не mysql ? А то я тут еще ускорил и стало интересно, а насколько сфинкс круче. Если не сложно, укажите исходное количество товаров для выборки(товаров в категории) и время получения результата с хотя бы "нативной" сортировкой по sort_order и name mysql> SELECT COUNT(*) as qty FROM product; +---------+ | qty | +---------+ | 1871817 | +---------+ 1 row in set (0.02 sec) mysql> SELECT id FROM main ORDER BY name DESC; +---------+ | id | +---------+ | 5989213 | | 6091563 | | 4350213 | | 4350196 | | 4350195 | | 4350197 | | 4350194 | | 4350192 | | 4350191 | | 4350193 | | 4350190 | | 4350217 | | 4350216 | | 5827378 | | 5827377 | | 5827376 | | 5827375 | | 5827374 | | 5827373 | | 5827372 | +---------+ 20 rows in set (0.16 sec) Но у вас так не получится! Сфинкс не всем раскрывает свои загадки! 2 Надіслати Поділитися на інших сайтах More sharing options... 100napb Опубліковано: 17 грудня 2019 Автор Share Опубліковано: 17 грудня 2019 3 hours ago, Yoda said: Но у вас так не получится! Сфинкс не всем раскрывает свои загадки! Спасибо большое за отклик и пример. Больше всего надеялся именно на Ваш ответ. Spoiler к сожалению а) у меня нет под рукой базы с таким количество реальных товаров. Но ради быстрого теста размножил имеющиеся, сохранив необходимую уникальность. б) аналогично Вашему примеру упростим запрос SELECT SQL_NO_CACHE COUNT(*) AS qty FROM product_; Запрос открыт за 0,039c [0,031c выполнение, 0,008c выборка] 1 строк выбрано qty --------------------- 2518592 SELECT SQL_NO_CACHE p.product_id FROM product_ p ORDER BY p.sort_order, p.name LIMIT 0,60; Запрос открыт за 0,048c [0,034c выполнение, 0,014c выборка] 60 строк выбрано product_id ----------- 3797248 3797247 3796136 ... без сфинкса, коробочная мариядб, даже не самая последняя. 1 Надіслати Поділитися на інших сайтах More sharing options... Yoda Опубліковано: 17 грудня 2019 Share Опубліковано: 17 грудня 2019 16 минут назад, 100napb сказал: Спасибо большое за отклик и пример. Больше всего надеялся именно на Ваш ответ. Показать контент к сожалению а) у меня нет под рукой базы с таким количество реальных товаров. Но ради быстрого теста размножил имеющиеся, сохранив необходимую уникальность. б) аналогично Вашему примеру упростим запрос SELECT SQL_NO_CACHE COUNT(*) AS qty FROM product_; Запрос открыт за 0,039c [0,031c выполнение, 0,008c выборка] 1 строк выбрано qty --------------------- 2518592 SELECT SQL_NO_CACHE p.product_id FROM product_ p ORDER BY p.sort_order, p.name LIMIT 0,60; Запрос открыт за 0,048c [0,034c выполнение, 0,014c выборка] 60 строк выбрано product_id ----------- 3797248 3797247 3796136 ... без сфинкса, коробочная мариядб, даже не самая последняя. А толку от него. sql запросы ограничены, просто взять и взять пихнуть в индекс базу не выйдет. Конфликтов с любым дополнением не оберешься. Любой фильтр в целом на категории до 5к товаров настраивается и с mysql базой. Как и любой магазин до 200-300к. Менять архитектуру хранилища, жертвуя совместимостью имеет смысл только в очень специфических случаях, когда вы будете уверены, что в любой момент сможете помочь клиенту со сторонними расширенями. Проблемы с индексацией начинаются где-то с 100к товаров, и зачастую их решение - это какие то не то что костыли а КОСТЫЛЮГИ! Чтобы подружить любой фильтр - надо как минимум написать самому фильтр. Поэтому там где не надо 50к товаров в одной категории, разворачивать сфинкс под каталог - это просто садить на иглу потенциального заказчика. Намного утилитарней, проще и эффективнее, сделать сводные таблицы (исключив лишние джоины) и расставить правильный порядок таблиц в запросе, как в фильтре у маэстро @SooR, так как в итоге это решение, в котором может разобраться любой разработчик. 2 Надіслати Поділитися на інших сайтах More sharing options... Створіть аккаунт або увійдіть для коментування Ви повинні бути користувачем, щоб залишити коментар Створити обліковий запис Зареєструйтеся для отримання облікового запису. Це просто! Зареєструвати аккаунт Вхід Уже зареєстровані? Увійдіть тут. Вхід зараз Share More sharing options... Передплатники 0 Перейти до списку тем Зараз на сторінці 0 користувачів Ні користувачів, які переглядиють цю сторінку Последние темы Последние дополнения Последние новости Вся активність Головна Разное Курилка ускорить sql-запрос из getProducts в /catalog/model/catalog/product.php Покупцям Оплата розширень фізичними особами Оплата розширень юридичними особами Політика повернень Розробникам Регламент розміщення розширень Регламент продажу та підтримки розширень Віртуальний обліковий запис автора Політика просування оголошень API каталогу розширень Вирішення спорів щодо авторських прав Корисна інформація Публічна оферта Політика повернень Політика конфіденційності Платіжна політика Політика передачі особистих даних Політика прозорості Останні розширення PRICE MASTER - Модуль імпорту/експорту товарів, парсинг, переклад, генерація текстів, редактор каталогу та багато іншого Автор: ScriptBrains 1.0 Синхронізація Замовлень Rozetka.ua та Opencart Автор: sinco Product Manipulator Автор: Hiperlynx007 Видалення дублікатів товарів для OpenCart Автор: Hatshypsut Вибір категорій і виробників для "Знайшли дешевше" шаблону Upstore Автор: Flint2000 × Уже зареєстровані? Ввійти Реєстрація Ваші замовлення Назад Придбані модулі та шаблони Ваші рахунки Лист очікувань Альтернативні контакти Форум Новини ocStore Назад Офіційний сайт Демо ocStore 3.0.3.2 Демо ocStore 2.3.0.2.4 Завантажити ocStore Документація Історія версій ocStore Блоги Модулі Шаблони Назад Безкоштовні шаблони Платні шаблони Де купувати модулі? Послуги FAQ OpenCart.Pro Назад Демо Купити Порівняння × Створити... Important Information На нашому сайті використовуються файли cookie і відбувається обробка деяких персональних даних користувачів, щоб поліпшити користувальницький інтерфейс. Щоб дізнатися для чого і які персональні дані ми обробляємо перейдіть за посиланням . Якщо Ви натиснете «Я даю згоду», це означає, що Ви розумієте і приймаєте всі умови, зазначені в цьому Повідомленні про конфіденційність. Я даю згоду
100napb Опубліковано: 20 жовтня 2019 Автор Share Опубліковано: 20 жовтня 2019 (змінено) 9 minutes ago, chukcha said: discount и special нельзя выносить из подзапроса 9 minutes ago, chukcha said: сделайте две одинаковых записи, или пересечение дат отсюда нельзя? Spoiler можно. тут получается нечто вроде цикла: для каждого значения\строки p.product_id, которое передается в этот подзоапрос будет вычисляться price. мой вариант не делает зависимого запроса (заменен джоином) и возвращает в точности тот же набор данных, что и нативный. Змінено 20 жовтня 2019 користувачем 100napb Надіслати Поділитися на інших сайтах More sharing options... 100napb Опубліковано: 20 жовтня 2019 Автор Share Опубліковано: 20 жовтня 2019 29 minutes ago, chukcha said: raiting можно считать / пресчитывать при появлении, изменении комментария - создав или отдельную таблицу или отдельное поле можно заморочиться. да. но стоит ли оно того? вроде затраты копеечные. даже если отзывов на проекте будет пару тысяч, думаю, картина не сильно изменится Spoiler Надіслати Поділитися на інших сайтах More sharing options... chukcha Опубліковано: 20 жовтня 2019 Share Опубліковано: 20 жовтня 2019 16 минут назад, 100napb сказал: но стоит ли оно того? Для одиночного запроса - несущественно Надіслати Поділитися на інших сайтах More sharing options... chukcha Опубліковано: 20 жовтня 2019 Share Опубліковано: 20 жовтня 2019 SELECT price FROM oc_product_discount pd2 WHERE pd2.product_id = p.product_id AND pd2.customer_group_id = '1' AND pd2.quantity = '1' AND ((pd2.date_start = '0000-00-00' OR pd2.date_start < NOW()) AND (pd2.date_end = '0000-00-00' OR pd2.date_end > NOW())) ORDER BY pd2.priority ASC, pd2.price ASC LIMIT 1 Сколько вернет записей? при Date_start:0000-00-00 Date_end:0000-00000 priority:1 и Date_start:2019-01-01 Date_end:2019-12-31 priority:0 А сколько SELECT * FROM oc_product p LEFT JOIN oc_product_discount pd2 ON (p.product_id = pd2.product_id ON (pd2.product_id = p.product_id AND pd2.customer_group_id = '1' AND pd2.quantity = '1' AND ((pd2.date_start = '0000-00-00' OR pd2.date_start < NOW()) AND (pd2.date_end = '0000-00-00' OR pd2.date_end > NOW()))) Для одного товара при пресечении дат? 1 Надіслати Поділитися на інших сайтах More sharing options... 100napb Опубліковано: 20 жовтня 2019 Автор Share Опубліковано: 20 жовтня 2019 (змінено) 2 hours ago, chukcha said: . понял о чем Вы. Респект за внимательность. Действительно, предложенный выше вариант не учитывал случая наличия конкурентных скидок или акций и не мог однозначно определить приоритетную (итоговую) цену. Виноват. Проглядел. Редкий кейс. Но запрос легко исправляется без каких-либо потерей в скорости (проверил). В спойлер ниже закинул и выделил цветом строки, которые решают этот недочет. Spoiler SELECT SQL_NO_CACHE p.product_id, rating.total AS rating, MIN(pd2.price) AS discount, MIN(ps.price) AS special FROM oc_product_to_category p2c 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) LEFT JOIN oc_product_special ps ON (p.product_id = ps.product_id AND ps.priority = (SELECT MIN(priority) FROM oc_product_special WHERE product_id = p.product_id AND customer_group_id = '1' AND ((date_start = '0000-00-00' OR date_start < NOW()) AND (date_end = '0000-00-00' OR date_end > NOW()))) AND customer_group_id = '1' AND ((ps.date_start = '0000-00-00' OR ps.date_start < NOW()) AND (ps.date_end = '0000-00-00' OR ps.date_end > NOW()))) LEFT JOIN oc_product_discount pd2 ON (pd2.product_id = p.product_id AND ps.priority = (SELECT MIN(priority) FROM oc_product_discount WHERE product_id = p.product_id AND customer_group_id = '1' AND ((date_start = '0000-00-00' OR date_start < NOW()) AND (date_end = '0000-00-00' OR date_end > NOW()))) AND pd2.customer_group_id = '1' AND pd2.quantity = '1' AND ((pd2.date_start = '0000-00-00' OR pd2.date_start < NOW()) AND (pd2.date_end = '0000-00-00' OR pd2.date_end > NOW()))) LEFT JOIN (SELECT AVG(rating) AS total, r1.product_id FROM oc_review r1 WHERE r1.status = '1' GROUP BY r1.product_id) AS rating ON p.product_id = rating.product_id WHERE pd.language_id = '1' AND p.status = '1' AND p.date_available <= NOW() AND p2s.store_id = '0' -- AND p2c.category_id = '37' GROUP BY p.product_id ORDER BY p.sort_order ASC, LCASE(pd.name) ASC LIMIT 0, 12 Змінено 20 жовтня 2019 користувачем 100napb Надіслати Поділитися на інших сайтах More sharing options... chukcha Опубліковано: 20 жовтня 2019 Share Опубліковано: 20 жовтня 2019 Я вам поведаю тайну что min и max не очень шустрые.. Все равно в getProduct эти подзапросы существуют А вот тут-то .. не хочу утверждать.. Не проверял, не знаю, но по оракл-опыту getProducts 1.SELECT *, sub_query getProduct 2.SELECT *, sub_query то если код sub_query одинаков до символа, то он будет закеширован и представлен в байткод на момент сессии коннекта. Надіслати Поділитися на інших сайтах More sharing options... 100napb Опубліковано: 20 жовтня 2019 Автор Share Опубліковано: 20 жовтня 2019 (змінено) 18 minutes ago, chukcha said: что min и max не очень шустрые.. все относительно. 1) тут им предстоит определить минимум для небольшого набора значений. очень небольшого 2) я действительно перепроверил результаты из стартового поста. Они актуальные с обновленным запросом Spoiler нативный запрос модифицированный запрос активный товар - этот тот, у которого p.status = 1, т.е. включенная карточка для 100 активных товаров: ~ 0.04сек; (0.04сек) для 6к активных товаров: ~0.4сек (0.2сек) для 19к активных товаров: ~ 2.1сек (0.6сек) для 33к активных товаров: ~2.3сек (1.3сек) для 100к активных товаров: ~7.1 сек (1.5сек) 18 minutes ago, chukcha said: то если код sub_query одинаков до символа, то он будет закеширован и представлен в байткод на момент сессии коннекта. тут, в мускуле\марии, проще и такой проблемы не случится. кэширование подзапросов действует только в рамках одного родительского запроса. на другие не распространяется. За эту оптимизацию отвечает параметр optimizer_switch='subquery_cache=OFF'. Гуглится легко. Строго говоря, мысль была простая: уйти от дорогих зависимых подзапросов в сторону более оптимизированных джоинов. И пока, вроде как, идея жизнеспособна ) Спасибо за замечания. Змінено 20 жовтня 2019 користувачем 100napb погуглил сам))) кажется, кэширование подзапросов - это фича только mariadb Надіслати Поділитися на інших сайтах More sharing options... 1 month later... 100napb Опубліковано: 16 грудня 2019 Автор Share Опубліковано: 16 грудня 2019 Уважаемые, а есть у кого-нибудь опыт\результаты по скорости выполнения запроса из getProducts, если основным хранилищем данных для него будет Sphinx, а не mysql ? А то я тут еще ускорил и стало интересно, а насколько сфинкс круче. Если не сложно, укажите исходное количество товаров для выборки(товаров в категории) и время получения результата с хотя бы "нативной" сортировкой по sort_order и name Надіслати Поділитися на інших сайтах More sharing options... Yoda Опубліковано: 17 грудня 2019 Share Опубліковано: 17 грудня 2019 В 16.12.2019 в 09:16, 100napb сказал: Уважаемые, а есть у кого-нибудь опыт\результаты по скорости выполнения запроса из getProducts, если основным хранилищем данных для него будет Sphinx, а не mysql ? А то я тут еще ускорил и стало интересно, а насколько сфинкс круче. Если не сложно, укажите исходное количество товаров для выборки(товаров в категории) и время получения результата с хотя бы "нативной" сортировкой по sort_order и name mysql> SELECT COUNT(*) as qty FROM product; +---------+ | qty | +---------+ | 1871817 | +---------+ 1 row in set (0.02 sec) mysql> SELECT id FROM main ORDER BY name DESC; +---------+ | id | +---------+ | 5989213 | | 6091563 | | 4350213 | | 4350196 | | 4350195 | | 4350197 | | 4350194 | | 4350192 | | 4350191 | | 4350193 | | 4350190 | | 4350217 | | 4350216 | | 5827378 | | 5827377 | | 5827376 | | 5827375 | | 5827374 | | 5827373 | | 5827372 | +---------+ 20 rows in set (0.16 sec) Но у вас так не получится! Сфинкс не всем раскрывает свои загадки! 2 Надіслати Поділитися на інших сайтах More sharing options... 100napb Опубліковано: 17 грудня 2019 Автор Share Опубліковано: 17 грудня 2019 3 hours ago, Yoda said: Но у вас так не получится! Сфинкс не всем раскрывает свои загадки! Спасибо большое за отклик и пример. Больше всего надеялся именно на Ваш ответ. Spoiler к сожалению а) у меня нет под рукой базы с таким количество реальных товаров. Но ради быстрого теста размножил имеющиеся, сохранив необходимую уникальность. б) аналогично Вашему примеру упростим запрос SELECT SQL_NO_CACHE COUNT(*) AS qty FROM product_; Запрос открыт за 0,039c [0,031c выполнение, 0,008c выборка] 1 строк выбрано qty --------------------- 2518592 SELECT SQL_NO_CACHE p.product_id FROM product_ p ORDER BY p.sort_order, p.name LIMIT 0,60; Запрос открыт за 0,048c [0,034c выполнение, 0,014c выборка] 60 строк выбрано product_id ----------- 3797248 3797247 3796136 ... без сфинкса, коробочная мариядб, даже не самая последняя. 1 Надіслати Поділитися на інших сайтах More sharing options... Yoda Опубліковано: 17 грудня 2019 Share Опубліковано: 17 грудня 2019 16 минут назад, 100napb сказал: Спасибо большое за отклик и пример. Больше всего надеялся именно на Ваш ответ. Показать контент к сожалению а) у меня нет под рукой базы с таким количество реальных товаров. Но ради быстрого теста размножил имеющиеся, сохранив необходимую уникальность. б) аналогично Вашему примеру упростим запрос SELECT SQL_NO_CACHE COUNT(*) AS qty FROM product_; Запрос открыт за 0,039c [0,031c выполнение, 0,008c выборка] 1 строк выбрано qty --------------------- 2518592 SELECT SQL_NO_CACHE p.product_id FROM product_ p ORDER BY p.sort_order, p.name LIMIT 0,60; Запрос открыт за 0,048c [0,034c выполнение, 0,014c выборка] 60 строк выбрано product_id ----------- 3797248 3797247 3796136 ... без сфинкса, коробочная мариядб, даже не самая последняя. А толку от него. sql запросы ограничены, просто взять и взять пихнуть в индекс базу не выйдет. Конфликтов с любым дополнением не оберешься. Любой фильтр в целом на категории до 5к товаров настраивается и с mysql базой. Как и любой магазин до 200-300к. Менять архитектуру хранилища, жертвуя совместимостью имеет смысл только в очень специфических случаях, когда вы будете уверены, что в любой момент сможете помочь клиенту со сторонними расширенями. Проблемы с индексацией начинаются где-то с 100к товаров, и зачастую их решение - это какие то не то что костыли а КОСТЫЛЮГИ! Чтобы подружить любой фильтр - надо как минимум написать самому фильтр. Поэтому там где не надо 50к товаров в одной категории, разворачивать сфинкс под каталог - это просто садить на иглу потенциального заказчика. Намного утилитарней, проще и эффективнее, сделать сводные таблицы (исключив лишние джоины) и расставить правильный порядок таблиц в запросе, как в фильтре у маэстро @SooR, так как в итоге это решение, в котором может разобраться любой разработчик. 2 Надіслати Поділитися на інших сайтах More sharing options... Створіть аккаунт або увійдіть для коментування Ви повинні бути користувачем, щоб залишити коментар Створити обліковий запис Зареєструйтеся для отримання облікового запису. Це просто! Зареєструвати аккаунт Вхід Уже зареєстровані? Увійдіть тут. Вхід зараз Share More sharing options... Передплатники 0 Перейти до списку тем Зараз на сторінці 0 користувачів Ні користувачів, які переглядиють цю сторінку Последние темы Последние дополнения Последние новости Вся активність Головна Разное Курилка ускорить sql-запрос из getProducts в /catalog/model/catalog/product.php Покупцям Оплата розширень фізичними особами Оплата розширень юридичними особами Політика повернень Розробникам Регламент розміщення розширень Регламент продажу та підтримки розширень Віртуальний обліковий запис автора Політика просування оголошень API каталогу розширень Вирішення спорів щодо авторських прав Корисна інформація Публічна оферта Політика повернень Політика конфіденційності Платіжна політика Політика передачі особистих даних Політика прозорості Останні розширення PRICE MASTER - Модуль імпорту/експорту товарів, парсинг, переклад, генерація текстів, редактор каталогу та багато іншого Автор: ScriptBrains 1.0 Синхронізація Замовлень Rozetka.ua та Opencart Автор: sinco Product Manipulator Автор: Hiperlynx007 Видалення дублікатів товарів для OpenCart Автор: Hatshypsut Вибір категорій і виробників для "Знайшли дешевше" шаблону Upstore Автор: Flint2000 × Уже зареєстровані? Ввійти Реєстрація Ваші замовлення Назад Придбані модулі та шаблони Ваші рахунки Лист очікувань Альтернативні контакти Форум Новини ocStore Назад Офіційний сайт Демо ocStore 3.0.3.2 Демо ocStore 2.3.0.2.4 Завантажити ocStore Документація Історія версій ocStore Блоги Модулі Шаблони Назад Безкоштовні шаблони Платні шаблони Де купувати модулі? Послуги FAQ OpenCart.Pro Назад Демо Купити Порівняння × Створити... Important Information На нашому сайті використовуються файли cookie і відбувається обробка деяких персональних даних користувачів, щоб поліпшити користувальницький інтерфейс. Щоб дізнатися для чого і які персональні дані ми обробляємо перейдіть за посиланням . Якщо Ви натиснете «Я даю згоду», це означає, що Ви розумієте і приймаєте всі умови, зазначені в цьому Повідомленні про конфіденційність. Я даю згоду
100napb Опубліковано: 20 жовтня 2019 Автор Share Опубліковано: 20 жовтня 2019 29 minutes ago, chukcha said: raiting можно считать / пресчитывать при появлении, изменении комментария - создав или отдельную таблицу или отдельное поле можно заморочиться. да. но стоит ли оно того? вроде затраты копеечные. даже если отзывов на проекте будет пару тысяч, думаю, картина не сильно изменится Spoiler Надіслати Поділитися на інших сайтах More sharing options... chukcha Опубліковано: 20 жовтня 2019 Share Опубліковано: 20 жовтня 2019 16 минут назад, 100napb сказал: но стоит ли оно того? Для одиночного запроса - несущественно Надіслати Поділитися на інших сайтах More sharing options... chukcha Опубліковано: 20 жовтня 2019 Share Опубліковано: 20 жовтня 2019 SELECT price FROM oc_product_discount pd2 WHERE pd2.product_id = p.product_id AND pd2.customer_group_id = '1' AND pd2.quantity = '1' AND ((pd2.date_start = '0000-00-00' OR pd2.date_start < NOW()) AND (pd2.date_end = '0000-00-00' OR pd2.date_end > NOW())) ORDER BY pd2.priority ASC, pd2.price ASC LIMIT 1 Сколько вернет записей? при Date_start:0000-00-00 Date_end:0000-00000 priority:1 и Date_start:2019-01-01 Date_end:2019-12-31 priority:0 А сколько SELECT * FROM oc_product p LEFT JOIN oc_product_discount pd2 ON (p.product_id = pd2.product_id ON (pd2.product_id = p.product_id AND pd2.customer_group_id = '1' AND pd2.quantity = '1' AND ((pd2.date_start = '0000-00-00' OR pd2.date_start < NOW()) AND (pd2.date_end = '0000-00-00' OR pd2.date_end > NOW()))) Для одного товара при пресечении дат? 1 Надіслати Поділитися на інших сайтах More sharing options... 100napb Опубліковано: 20 жовтня 2019 Автор Share Опубліковано: 20 жовтня 2019 (змінено) 2 hours ago, chukcha said: . понял о чем Вы. Респект за внимательность. Действительно, предложенный выше вариант не учитывал случая наличия конкурентных скидок или акций и не мог однозначно определить приоритетную (итоговую) цену. Виноват. Проглядел. Редкий кейс. Но запрос легко исправляется без каких-либо потерей в скорости (проверил). В спойлер ниже закинул и выделил цветом строки, которые решают этот недочет. Spoiler SELECT SQL_NO_CACHE p.product_id, rating.total AS rating, MIN(pd2.price) AS discount, MIN(ps.price) AS special FROM oc_product_to_category p2c 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) LEFT JOIN oc_product_special ps ON (p.product_id = ps.product_id AND ps.priority = (SELECT MIN(priority) FROM oc_product_special WHERE product_id = p.product_id AND customer_group_id = '1' AND ((date_start = '0000-00-00' OR date_start < NOW()) AND (date_end = '0000-00-00' OR date_end > NOW()))) AND customer_group_id = '1' AND ((ps.date_start = '0000-00-00' OR ps.date_start < NOW()) AND (ps.date_end = '0000-00-00' OR ps.date_end > NOW()))) LEFT JOIN oc_product_discount pd2 ON (pd2.product_id = p.product_id AND ps.priority = (SELECT MIN(priority) FROM oc_product_discount WHERE product_id = p.product_id AND customer_group_id = '1' AND ((date_start = '0000-00-00' OR date_start < NOW()) AND (date_end = '0000-00-00' OR date_end > NOW()))) AND pd2.customer_group_id = '1' AND pd2.quantity = '1' AND ((pd2.date_start = '0000-00-00' OR pd2.date_start < NOW()) AND (pd2.date_end = '0000-00-00' OR pd2.date_end > NOW()))) LEFT JOIN (SELECT AVG(rating) AS total, r1.product_id FROM oc_review r1 WHERE r1.status = '1' GROUP BY r1.product_id) AS rating ON p.product_id = rating.product_id WHERE pd.language_id = '1' AND p.status = '1' AND p.date_available <= NOW() AND p2s.store_id = '0' -- AND p2c.category_id = '37' GROUP BY p.product_id ORDER BY p.sort_order ASC, LCASE(pd.name) ASC LIMIT 0, 12 Змінено 20 жовтня 2019 користувачем 100napb Надіслати Поділитися на інших сайтах More sharing options... chukcha Опубліковано: 20 жовтня 2019 Share Опубліковано: 20 жовтня 2019 Я вам поведаю тайну что min и max не очень шустрые.. Все равно в getProduct эти подзапросы существуют А вот тут-то .. не хочу утверждать.. Не проверял, не знаю, но по оракл-опыту getProducts 1.SELECT *, sub_query getProduct 2.SELECT *, sub_query то если код sub_query одинаков до символа, то он будет закеширован и представлен в байткод на момент сессии коннекта. Надіслати Поділитися на інших сайтах More sharing options... 100napb Опубліковано: 20 жовтня 2019 Автор Share Опубліковано: 20 жовтня 2019 (змінено) 18 minutes ago, chukcha said: что min и max не очень шустрые.. все относительно. 1) тут им предстоит определить минимум для небольшого набора значений. очень небольшого 2) я действительно перепроверил результаты из стартового поста. Они актуальные с обновленным запросом Spoiler нативный запрос модифицированный запрос активный товар - этот тот, у которого p.status = 1, т.е. включенная карточка для 100 активных товаров: ~ 0.04сек; (0.04сек) для 6к активных товаров: ~0.4сек (0.2сек) для 19к активных товаров: ~ 2.1сек (0.6сек) для 33к активных товаров: ~2.3сек (1.3сек) для 100к активных товаров: ~7.1 сек (1.5сек) 18 minutes ago, chukcha said: то если код sub_query одинаков до символа, то он будет закеширован и представлен в байткод на момент сессии коннекта. тут, в мускуле\марии, проще и такой проблемы не случится. кэширование подзапросов действует только в рамках одного родительского запроса. на другие не распространяется. За эту оптимизацию отвечает параметр optimizer_switch='subquery_cache=OFF'. Гуглится легко. Строго говоря, мысль была простая: уйти от дорогих зависимых подзапросов в сторону более оптимизированных джоинов. И пока, вроде как, идея жизнеспособна ) Спасибо за замечания. Змінено 20 жовтня 2019 користувачем 100napb погуглил сам))) кажется, кэширование подзапросов - это фича только mariadb Надіслати Поділитися на інших сайтах More sharing options... 1 month later... 100napb Опубліковано: 16 грудня 2019 Автор Share Опубліковано: 16 грудня 2019 Уважаемые, а есть у кого-нибудь опыт\результаты по скорости выполнения запроса из getProducts, если основным хранилищем данных для него будет Sphinx, а не mysql ? А то я тут еще ускорил и стало интересно, а насколько сфинкс круче. Если не сложно, укажите исходное количество товаров для выборки(товаров в категории) и время получения результата с хотя бы "нативной" сортировкой по sort_order и name Надіслати Поділитися на інших сайтах More sharing options... Yoda Опубліковано: 17 грудня 2019 Share Опубліковано: 17 грудня 2019 В 16.12.2019 в 09:16, 100napb сказал: Уважаемые, а есть у кого-нибудь опыт\результаты по скорости выполнения запроса из getProducts, если основным хранилищем данных для него будет Sphinx, а не mysql ? А то я тут еще ускорил и стало интересно, а насколько сфинкс круче. Если не сложно, укажите исходное количество товаров для выборки(товаров в категории) и время получения результата с хотя бы "нативной" сортировкой по sort_order и name mysql> SELECT COUNT(*) as qty FROM product; +---------+ | qty | +---------+ | 1871817 | +---------+ 1 row in set (0.02 sec) mysql> SELECT id FROM main ORDER BY name DESC; +---------+ | id | +---------+ | 5989213 | | 6091563 | | 4350213 | | 4350196 | | 4350195 | | 4350197 | | 4350194 | | 4350192 | | 4350191 | | 4350193 | | 4350190 | | 4350217 | | 4350216 | | 5827378 | | 5827377 | | 5827376 | | 5827375 | | 5827374 | | 5827373 | | 5827372 | +---------+ 20 rows in set (0.16 sec) Но у вас так не получится! Сфинкс не всем раскрывает свои загадки! 2 Надіслати Поділитися на інших сайтах More sharing options... 100napb Опубліковано: 17 грудня 2019 Автор Share Опубліковано: 17 грудня 2019 3 hours ago, Yoda said: Но у вас так не получится! Сфинкс не всем раскрывает свои загадки! Спасибо большое за отклик и пример. Больше всего надеялся именно на Ваш ответ. Spoiler к сожалению а) у меня нет под рукой базы с таким количество реальных товаров. Но ради быстрого теста размножил имеющиеся, сохранив необходимую уникальность. б) аналогично Вашему примеру упростим запрос SELECT SQL_NO_CACHE COUNT(*) AS qty FROM product_; Запрос открыт за 0,039c [0,031c выполнение, 0,008c выборка] 1 строк выбрано qty --------------------- 2518592 SELECT SQL_NO_CACHE p.product_id FROM product_ p ORDER BY p.sort_order, p.name LIMIT 0,60; Запрос открыт за 0,048c [0,034c выполнение, 0,014c выборка] 60 строк выбрано product_id ----------- 3797248 3797247 3796136 ... без сфинкса, коробочная мариядб, даже не самая последняя. 1 Надіслати Поділитися на інших сайтах More sharing options... Yoda Опубліковано: 17 грудня 2019 Share Опубліковано: 17 грудня 2019 16 минут назад, 100napb сказал: Спасибо большое за отклик и пример. Больше всего надеялся именно на Ваш ответ. Показать контент к сожалению а) у меня нет под рукой базы с таким количество реальных товаров. Но ради быстрого теста размножил имеющиеся, сохранив необходимую уникальность. б) аналогично Вашему примеру упростим запрос SELECT SQL_NO_CACHE COUNT(*) AS qty FROM product_; Запрос открыт за 0,039c [0,031c выполнение, 0,008c выборка] 1 строк выбрано qty --------------------- 2518592 SELECT SQL_NO_CACHE p.product_id FROM product_ p ORDER BY p.sort_order, p.name LIMIT 0,60; Запрос открыт за 0,048c [0,034c выполнение, 0,014c выборка] 60 строк выбрано product_id ----------- 3797248 3797247 3796136 ... без сфинкса, коробочная мариядб, даже не самая последняя. А толку от него. sql запросы ограничены, просто взять и взять пихнуть в индекс базу не выйдет. Конфликтов с любым дополнением не оберешься. Любой фильтр в целом на категории до 5к товаров настраивается и с mysql базой. Как и любой магазин до 200-300к. Менять архитектуру хранилища, жертвуя совместимостью имеет смысл только в очень специфических случаях, когда вы будете уверены, что в любой момент сможете помочь клиенту со сторонними расширенями. Проблемы с индексацией начинаются где-то с 100к товаров, и зачастую их решение - это какие то не то что костыли а КОСТЫЛЮГИ! Чтобы подружить любой фильтр - надо как минимум написать самому фильтр. Поэтому там где не надо 50к товаров в одной категории, разворачивать сфинкс под каталог - это просто садить на иглу потенциального заказчика. Намного утилитарней, проще и эффективнее, сделать сводные таблицы (исключив лишние джоины) и расставить правильный порядок таблиц в запросе, как в фильтре у маэстро @SooR, так как в итоге это решение, в котором может разобраться любой разработчик. 2 Надіслати Поділитися на інших сайтах More sharing options... Створіть аккаунт або увійдіть для коментування Ви повинні бути користувачем, щоб залишити коментар Створити обліковий запис Зареєструйтеся для отримання облікового запису. Це просто! Зареєструвати аккаунт Вхід Уже зареєстровані? Увійдіть тут. Вхід зараз Share More sharing options... Передплатники 0 Перейти до списку тем Зараз на сторінці 0 користувачів Ні користувачів, які переглядиють цю сторінку Последние темы Последние дополнения Последние новости Вся активність Головна Разное Курилка ускорить sql-запрос из getProducts в /catalog/model/catalog/product.php Покупцям Оплата розширень фізичними особами Оплата розширень юридичними особами Політика повернень Розробникам Регламент розміщення розширень Регламент продажу та підтримки розширень Віртуальний обліковий запис автора Політика просування оголошень API каталогу розширень Вирішення спорів щодо авторських прав Корисна інформація Публічна оферта Політика повернень Політика конфіденційності Платіжна політика Політика передачі особистих даних Політика прозорості Останні розширення PRICE MASTER - Модуль імпорту/експорту товарів, парсинг, переклад, генерація текстів, редактор каталогу та багато іншого Автор: ScriptBrains 1.0 Синхронізація Замовлень Rozetka.ua та Opencart Автор: sinco Product Manipulator Автор: Hiperlynx007 Видалення дублікатів товарів для OpenCart Автор: Hatshypsut Вибір категорій і виробників для "Знайшли дешевше" шаблону Upstore Автор: Flint2000 × Уже зареєстровані? Ввійти Реєстрація Ваші замовлення Назад Придбані модулі та шаблони Ваші рахунки Лист очікувань Альтернативні контакти Форум Новини ocStore Назад Офіційний сайт Демо ocStore 3.0.3.2 Демо ocStore 2.3.0.2.4 Завантажити ocStore Документація Історія версій ocStore Блоги Модулі Шаблони Назад Безкоштовні шаблони Платні шаблони Де купувати модулі? Послуги FAQ OpenCart.Pro Назад Демо Купити Порівняння × Створити... Important Information На нашому сайті використовуються файли cookie і відбувається обробка деяких персональних даних користувачів, щоб поліпшити користувальницький інтерфейс. Щоб дізнатися для чого і які персональні дані ми обробляємо перейдіть за посиланням . Якщо Ви натиснете «Я даю згоду», це означає, що Ви розумієте і приймаєте всі умови, зазначені в цьому Повідомленні про конфіденційність. Я даю згоду
chukcha Опубліковано: 20 жовтня 2019 Share Опубліковано: 20 жовтня 2019 16 минут назад, 100napb сказал: но стоит ли оно того? Для одиночного запроса - несущественно Надіслати Поділитися на інших сайтах More sharing options... chukcha Опубліковано: 20 жовтня 2019 Share Опубліковано: 20 жовтня 2019 SELECT price FROM oc_product_discount pd2 WHERE pd2.product_id = p.product_id AND pd2.customer_group_id = '1' AND pd2.quantity = '1' AND ((pd2.date_start = '0000-00-00' OR pd2.date_start < NOW()) AND (pd2.date_end = '0000-00-00' OR pd2.date_end > NOW())) ORDER BY pd2.priority ASC, pd2.price ASC LIMIT 1 Сколько вернет записей? при Date_start:0000-00-00 Date_end:0000-00000 priority:1 и Date_start:2019-01-01 Date_end:2019-12-31 priority:0 А сколько SELECT * FROM oc_product p LEFT JOIN oc_product_discount pd2 ON (p.product_id = pd2.product_id ON (pd2.product_id = p.product_id AND pd2.customer_group_id = '1' AND pd2.quantity = '1' AND ((pd2.date_start = '0000-00-00' OR pd2.date_start < NOW()) AND (pd2.date_end = '0000-00-00' OR pd2.date_end > NOW()))) Для одного товара при пресечении дат? 1 Надіслати Поділитися на інших сайтах More sharing options... 100napb Опубліковано: 20 жовтня 2019 Автор Share Опубліковано: 20 жовтня 2019 (змінено) 2 hours ago, chukcha said: . понял о чем Вы. Респект за внимательность. Действительно, предложенный выше вариант не учитывал случая наличия конкурентных скидок или акций и не мог однозначно определить приоритетную (итоговую) цену. Виноват. Проглядел. Редкий кейс. Но запрос легко исправляется без каких-либо потерей в скорости (проверил). В спойлер ниже закинул и выделил цветом строки, которые решают этот недочет. Spoiler SELECT SQL_NO_CACHE p.product_id, rating.total AS rating, MIN(pd2.price) AS discount, MIN(ps.price) AS special FROM oc_product_to_category p2c 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) LEFT JOIN oc_product_special ps ON (p.product_id = ps.product_id AND ps.priority = (SELECT MIN(priority) FROM oc_product_special WHERE product_id = p.product_id AND customer_group_id = '1' AND ((date_start = '0000-00-00' OR date_start < NOW()) AND (date_end = '0000-00-00' OR date_end > NOW()))) AND customer_group_id = '1' AND ((ps.date_start = '0000-00-00' OR ps.date_start < NOW()) AND (ps.date_end = '0000-00-00' OR ps.date_end > NOW()))) LEFT JOIN oc_product_discount pd2 ON (pd2.product_id = p.product_id AND ps.priority = (SELECT MIN(priority) FROM oc_product_discount WHERE product_id = p.product_id AND customer_group_id = '1' AND ((date_start = '0000-00-00' OR date_start < NOW()) AND (date_end = '0000-00-00' OR date_end > NOW()))) AND pd2.customer_group_id = '1' AND pd2.quantity = '1' AND ((pd2.date_start = '0000-00-00' OR pd2.date_start < NOW()) AND (pd2.date_end = '0000-00-00' OR pd2.date_end > NOW()))) LEFT JOIN (SELECT AVG(rating) AS total, r1.product_id FROM oc_review r1 WHERE r1.status = '1' GROUP BY r1.product_id) AS rating ON p.product_id = rating.product_id WHERE pd.language_id = '1' AND p.status = '1' AND p.date_available <= NOW() AND p2s.store_id = '0' -- AND p2c.category_id = '37' GROUP BY p.product_id ORDER BY p.sort_order ASC, LCASE(pd.name) ASC LIMIT 0, 12 Змінено 20 жовтня 2019 користувачем 100napb Надіслати Поділитися на інших сайтах More sharing options... chukcha Опубліковано: 20 жовтня 2019 Share Опубліковано: 20 жовтня 2019 Я вам поведаю тайну что min и max не очень шустрые.. Все равно в getProduct эти подзапросы существуют А вот тут-то .. не хочу утверждать.. Не проверял, не знаю, но по оракл-опыту getProducts 1.SELECT *, sub_query getProduct 2.SELECT *, sub_query то если код sub_query одинаков до символа, то он будет закеширован и представлен в байткод на момент сессии коннекта. Надіслати Поділитися на інших сайтах More sharing options... 100napb Опубліковано: 20 жовтня 2019 Автор Share Опубліковано: 20 жовтня 2019 (змінено) 18 minutes ago, chukcha said: что min и max не очень шустрые.. все относительно. 1) тут им предстоит определить минимум для небольшого набора значений. очень небольшого 2) я действительно перепроверил результаты из стартового поста. Они актуальные с обновленным запросом Spoiler нативный запрос модифицированный запрос активный товар - этот тот, у которого p.status = 1, т.е. включенная карточка для 100 активных товаров: ~ 0.04сек; (0.04сек) для 6к активных товаров: ~0.4сек (0.2сек) для 19к активных товаров: ~ 2.1сек (0.6сек) для 33к активных товаров: ~2.3сек (1.3сек) для 100к активных товаров: ~7.1 сек (1.5сек) 18 minutes ago, chukcha said: то если код sub_query одинаков до символа, то он будет закеширован и представлен в байткод на момент сессии коннекта. тут, в мускуле\марии, проще и такой проблемы не случится. кэширование подзапросов действует только в рамках одного родительского запроса. на другие не распространяется. За эту оптимизацию отвечает параметр optimizer_switch='subquery_cache=OFF'. Гуглится легко. Строго говоря, мысль была простая: уйти от дорогих зависимых подзапросов в сторону более оптимизированных джоинов. И пока, вроде как, идея жизнеспособна ) Спасибо за замечания. Змінено 20 жовтня 2019 користувачем 100napb погуглил сам))) кажется, кэширование подзапросов - это фича только mariadb Надіслати Поділитися на інших сайтах More sharing options... 1 month later... 100napb Опубліковано: 16 грудня 2019 Автор Share Опубліковано: 16 грудня 2019 Уважаемые, а есть у кого-нибудь опыт\результаты по скорости выполнения запроса из getProducts, если основным хранилищем данных для него будет Sphinx, а не mysql ? А то я тут еще ускорил и стало интересно, а насколько сфинкс круче. Если не сложно, укажите исходное количество товаров для выборки(товаров в категории) и время получения результата с хотя бы "нативной" сортировкой по sort_order и name Надіслати Поділитися на інших сайтах More sharing options... Yoda Опубліковано: 17 грудня 2019 Share Опубліковано: 17 грудня 2019 В 16.12.2019 в 09:16, 100napb сказал: Уважаемые, а есть у кого-нибудь опыт\результаты по скорости выполнения запроса из getProducts, если основным хранилищем данных для него будет Sphinx, а не mysql ? А то я тут еще ускорил и стало интересно, а насколько сфинкс круче. Если не сложно, укажите исходное количество товаров для выборки(товаров в категории) и время получения результата с хотя бы "нативной" сортировкой по sort_order и name mysql> SELECT COUNT(*) as qty FROM product; +---------+ | qty | +---------+ | 1871817 | +---------+ 1 row in set (0.02 sec) mysql> SELECT id FROM main ORDER BY name DESC; +---------+ | id | +---------+ | 5989213 | | 6091563 | | 4350213 | | 4350196 | | 4350195 | | 4350197 | | 4350194 | | 4350192 | | 4350191 | | 4350193 | | 4350190 | | 4350217 | | 4350216 | | 5827378 | | 5827377 | | 5827376 | | 5827375 | | 5827374 | | 5827373 | | 5827372 | +---------+ 20 rows in set (0.16 sec) Но у вас так не получится! Сфинкс не всем раскрывает свои загадки! 2 Надіслати Поділитися на інших сайтах More sharing options... 100napb Опубліковано: 17 грудня 2019 Автор Share Опубліковано: 17 грудня 2019 3 hours ago, Yoda said: Но у вас так не получится! Сфинкс не всем раскрывает свои загадки! Спасибо большое за отклик и пример. Больше всего надеялся именно на Ваш ответ. Spoiler к сожалению а) у меня нет под рукой базы с таким количество реальных товаров. Но ради быстрого теста размножил имеющиеся, сохранив необходимую уникальность. б) аналогично Вашему примеру упростим запрос SELECT SQL_NO_CACHE COUNT(*) AS qty FROM product_; Запрос открыт за 0,039c [0,031c выполнение, 0,008c выборка] 1 строк выбрано qty --------------------- 2518592 SELECT SQL_NO_CACHE p.product_id FROM product_ p ORDER BY p.sort_order, p.name LIMIT 0,60; Запрос открыт за 0,048c [0,034c выполнение, 0,014c выборка] 60 строк выбрано product_id ----------- 3797248 3797247 3796136 ... без сфинкса, коробочная мариядб, даже не самая последняя. 1 Надіслати Поділитися на інших сайтах More sharing options... Yoda Опубліковано: 17 грудня 2019 Share Опубліковано: 17 грудня 2019 16 минут назад, 100napb сказал: Спасибо большое за отклик и пример. Больше всего надеялся именно на Ваш ответ. Показать контент к сожалению а) у меня нет под рукой базы с таким количество реальных товаров. Но ради быстрого теста размножил имеющиеся, сохранив необходимую уникальность. б) аналогично Вашему примеру упростим запрос SELECT SQL_NO_CACHE COUNT(*) AS qty FROM product_; Запрос открыт за 0,039c [0,031c выполнение, 0,008c выборка] 1 строк выбрано qty --------------------- 2518592 SELECT SQL_NO_CACHE p.product_id FROM product_ p ORDER BY p.sort_order, p.name LIMIT 0,60; Запрос открыт за 0,048c [0,034c выполнение, 0,014c выборка] 60 строк выбрано product_id ----------- 3797248 3797247 3796136 ... без сфинкса, коробочная мариядб, даже не самая последняя. А толку от него. sql запросы ограничены, просто взять и взять пихнуть в индекс базу не выйдет. Конфликтов с любым дополнением не оберешься. Любой фильтр в целом на категории до 5к товаров настраивается и с mysql базой. Как и любой магазин до 200-300к. Менять архитектуру хранилища, жертвуя совместимостью имеет смысл только в очень специфических случаях, когда вы будете уверены, что в любой момент сможете помочь клиенту со сторонними расширенями. Проблемы с индексацией начинаются где-то с 100к товаров, и зачастую их решение - это какие то не то что костыли а КОСТЫЛЮГИ! Чтобы подружить любой фильтр - надо как минимум написать самому фильтр. Поэтому там где не надо 50к товаров в одной категории, разворачивать сфинкс под каталог - это просто садить на иглу потенциального заказчика. Намного утилитарней, проще и эффективнее, сделать сводные таблицы (исключив лишние джоины) и расставить правильный порядок таблиц в запросе, как в фильтре у маэстро @SooR, так как в итоге это решение, в котором может разобраться любой разработчик. 2 Надіслати Поділитися на інших сайтах More sharing options... Створіть аккаунт або увійдіть для коментування Ви повинні бути користувачем, щоб залишити коментар Створити обліковий запис Зареєструйтеся для отримання облікового запису. Це просто! Зареєструвати аккаунт Вхід Уже зареєстровані? Увійдіть тут. Вхід зараз Share More sharing options... Передплатники 0 Перейти до списку тем Зараз на сторінці 0 користувачів Ні користувачів, які переглядиють цю сторінку Последние темы Последние дополнения Последние новости Вся активність Головна Разное Курилка ускорить sql-запрос из getProducts в /catalog/model/catalog/product.php Покупцям Оплата розширень фізичними особами Оплата розширень юридичними особами Політика повернень Розробникам Регламент розміщення розширень Регламент продажу та підтримки розширень Віртуальний обліковий запис автора Політика просування оголошень API каталогу розширень Вирішення спорів щодо авторських прав Корисна інформація Публічна оферта Політика повернень Політика конфіденційності Платіжна політика Політика передачі особистих даних Політика прозорості Останні розширення PRICE MASTER - Модуль імпорту/експорту товарів, парсинг, переклад, генерація текстів, редактор каталогу та багато іншого Автор: ScriptBrains 1.0 Синхронізація Замовлень Rozetka.ua та Opencart Автор: sinco Product Manipulator Автор: Hiperlynx007 Видалення дублікатів товарів для OpenCart Автор: Hatshypsut Вибір категорій і виробників для "Знайшли дешевше" шаблону Upstore Автор: Flint2000 × Уже зареєстровані? Ввійти Реєстрація Ваші замовлення Назад Придбані модулі та шаблони Ваші рахунки Лист очікувань Альтернативні контакти Форум Новини ocStore Назад Офіційний сайт Демо ocStore 3.0.3.2 Демо ocStore 2.3.0.2.4 Завантажити ocStore Документація Історія версій ocStore Блоги Модулі Шаблони Назад Безкоштовні шаблони Платні шаблони Де купувати модулі? Послуги FAQ OpenCart.Pro Назад Демо Купити Порівняння × Створити... Important Information На нашому сайті використовуються файли cookie і відбувається обробка деяких персональних даних користувачів, щоб поліпшити користувальницький інтерфейс. Щоб дізнатися для чого і які персональні дані ми обробляємо перейдіть за посиланням . Якщо Ви натиснете «Я даю згоду», це означає, що Ви розумієте і приймаєте всі умови, зазначені в цьому Повідомленні про конфіденційність. Я даю згоду
chukcha Опубліковано: 20 жовтня 2019 Share Опубліковано: 20 жовтня 2019 SELECT price FROM oc_product_discount pd2 WHERE pd2.product_id = p.product_id AND pd2.customer_group_id = '1' AND pd2.quantity = '1' AND ((pd2.date_start = '0000-00-00' OR pd2.date_start < NOW()) AND (pd2.date_end = '0000-00-00' OR pd2.date_end > NOW())) ORDER BY pd2.priority ASC, pd2.price ASC LIMIT 1 Сколько вернет записей? при Date_start:0000-00-00 Date_end:0000-00000 priority:1 и Date_start:2019-01-01 Date_end:2019-12-31 priority:0 А сколько SELECT * FROM oc_product p LEFT JOIN oc_product_discount pd2 ON (p.product_id = pd2.product_id ON (pd2.product_id = p.product_id AND pd2.customer_group_id = '1' AND pd2.quantity = '1' AND ((pd2.date_start = '0000-00-00' OR pd2.date_start < NOW()) AND (pd2.date_end = '0000-00-00' OR pd2.date_end > NOW()))) Для одного товара при пресечении дат? 1 Надіслати Поділитися на інших сайтах More sharing options... 100napb Опубліковано: 20 жовтня 2019 Автор Share Опубліковано: 20 жовтня 2019 (змінено) 2 hours ago, chukcha said: . понял о чем Вы. Респект за внимательность. Действительно, предложенный выше вариант не учитывал случая наличия конкурентных скидок или акций и не мог однозначно определить приоритетную (итоговую) цену. Виноват. Проглядел. Редкий кейс. Но запрос легко исправляется без каких-либо потерей в скорости (проверил). В спойлер ниже закинул и выделил цветом строки, которые решают этот недочет. Spoiler SELECT SQL_NO_CACHE p.product_id, rating.total AS rating, MIN(pd2.price) AS discount, MIN(ps.price) AS special FROM oc_product_to_category p2c 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) LEFT JOIN oc_product_special ps ON (p.product_id = ps.product_id AND ps.priority = (SELECT MIN(priority) FROM oc_product_special WHERE product_id = p.product_id AND customer_group_id = '1' AND ((date_start = '0000-00-00' OR date_start < NOW()) AND (date_end = '0000-00-00' OR date_end > NOW()))) AND customer_group_id = '1' AND ((ps.date_start = '0000-00-00' OR ps.date_start < NOW()) AND (ps.date_end = '0000-00-00' OR ps.date_end > NOW()))) LEFT JOIN oc_product_discount pd2 ON (pd2.product_id = p.product_id AND ps.priority = (SELECT MIN(priority) FROM oc_product_discount WHERE product_id = p.product_id AND customer_group_id = '1' AND ((date_start = '0000-00-00' OR date_start < NOW()) AND (date_end = '0000-00-00' OR date_end > NOW()))) AND pd2.customer_group_id = '1' AND pd2.quantity = '1' AND ((pd2.date_start = '0000-00-00' OR pd2.date_start < NOW()) AND (pd2.date_end = '0000-00-00' OR pd2.date_end > NOW()))) LEFT JOIN (SELECT AVG(rating) AS total, r1.product_id FROM oc_review r1 WHERE r1.status = '1' GROUP BY r1.product_id) AS rating ON p.product_id = rating.product_id WHERE pd.language_id = '1' AND p.status = '1' AND p.date_available <= NOW() AND p2s.store_id = '0' -- AND p2c.category_id = '37' GROUP BY p.product_id ORDER BY p.sort_order ASC, LCASE(pd.name) ASC LIMIT 0, 12 Змінено 20 жовтня 2019 користувачем 100napb Надіслати Поділитися на інших сайтах More sharing options... chukcha Опубліковано: 20 жовтня 2019 Share Опубліковано: 20 жовтня 2019 Я вам поведаю тайну что min и max не очень шустрые.. Все равно в getProduct эти подзапросы существуют А вот тут-то .. не хочу утверждать.. Не проверял, не знаю, но по оракл-опыту getProducts 1.SELECT *, sub_query getProduct 2.SELECT *, sub_query то если код sub_query одинаков до символа, то он будет закеширован и представлен в байткод на момент сессии коннекта. Надіслати Поділитися на інших сайтах More sharing options... 100napb Опубліковано: 20 жовтня 2019 Автор Share Опубліковано: 20 жовтня 2019 (змінено) 18 minutes ago, chukcha said: что min и max не очень шустрые.. все относительно. 1) тут им предстоит определить минимум для небольшого набора значений. очень небольшого 2) я действительно перепроверил результаты из стартового поста. Они актуальные с обновленным запросом Spoiler нативный запрос модифицированный запрос активный товар - этот тот, у которого p.status = 1, т.е. включенная карточка для 100 активных товаров: ~ 0.04сек; (0.04сек) для 6к активных товаров: ~0.4сек (0.2сек) для 19к активных товаров: ~ 2.1сек (0.6сек) для 33к активных товаров: ~2.3сек (1.3сек) для 100к активных товаров: ~7.1 сек (1.5сек) 18 minutes ago, chukcha said: то если код sub_query одинаков до символа, то он будет закеширован и представлен в байткод на момент сессии коннекта. тут, в мускуле\марии, проще и такой проблемы не случится. кэширование подзапросов действует только в рамках одного родительского запроса. на другие не распространяется. За эту оптимизацию отвечает параметр optimizer_switch='subquery_cache=OFF'. Гуглится легко. Строго говоря, мысль была простая: уйти от дорогих зависимых подзапросов в сторону более оптимизированных джоинов. И пока, вроде как, идея жизнеспособна ) Спасибо за замечания. Змінено 20 жовтня 2019 користувачем 100napb погуглил сам))) кажется, кэширование подзапросов - это фича только mariadb Надіслати Поділитися на інших сайтах More sharing options... 1 month later... 100napb Опубліковано: 16 грудня 2019 Автор Share Опубліковано: 16 грудня 2019 Уважаемые, а есть у кого-нибудь опыт\результаты по скорости выполнения запроса из getProducts, если основным хранилищем данных для него будет Sphinx, а не mysql ? А то я тут еще ускорил и стало интересно, а насколько сфинкс круче. Если не сложно, укажите исходное количество товаров для выборки(товаров в категории) и время получения результата с хотя бы "нативной" сортировкой по sort_order и name Надіслати Поділитися на інших сайтах More sharing options... Yoda Опубліковано: 17 грудня 2019 Share Опубліковано: 17 грудня 2019 В 16.12.2019 в 09:16, 100napb сказал: Уважаемые, а есть у кого-нибудь опыт\результаты по скорости выполнения запроса из getProducts, если основным хранилищем данных для него будет Sphinx, а не mysql ? А то я тут еще ускорил и стало интересно, а насколько сфинкс круче. Если не сложно, укажите исходное количество товаров для выборки(товаров в категории) и время получения результата с хотя бы "нативной" сортировкой по sort_order и name mysql> SELECT COUNT(*) as qty FROM product; +---------+ | qty | +---------+ | 1871817 | +---------+ 1 row in set (0.02 sec) mysql> SELECT id FROM main ORDER BY name DESC; +---------+ | id | +---------+ | 5989213 | | 6091563 | | 4350213 | | 4350196 | | 4350195 | | 4350197 | | 4350194 | | 4350192 | | 4350191 | | 4350193 | | 4350190 | | 4350217 | | 4350216 | | 5827378 | | 5827377 | | 5827376 | | 5827375 | | 5827374 | | 5827373 | | 5827372 | +---------+ 20 rows in set (0.16 sec) Но у вас так не получится! Сфинкс не всем раскрывает свои загадки! 2 Надіслати Поділитися на інших сайтах More sharing options... 100napb Опубліковано: 17 грудня 2019 Автор Share Опубліковано: 17 грудня 2019 3 hours ago, Yoda said: Но у вас так не получится! Сфинкс не всем раскрывает свои загадки! Спасибо большое за отклик и пример. Больше всего надеялся именно на Ваш ответ. Spoiler к сожалению а) у меня нет под рукой базы с таким количество реальных товаров. Но ради быстрого теста размножил имеющиеся, сохранив необходимую уникальность. б) аналогично Вашему примеру упростим запрос SELECT SQL_NO_CACHE COUNT(*) AS qty FROM product_; Запрос открыт за 0,039c [0,031c выполнение, 0,008c выборка] 1 строк выбрано qty --------------------- 2518592 SELECT SQL_NO_CACHE p.product_id FROM product_ p ORDER BY p.sort_order, p.name LIMIT 0,60; Запрос открыт за 0,048c [0,034c выполнение, 0,014c выборка] 60 строк выбрано product_id ----------- 3797248 3797247 3796136 ... без сфинкса, коробочная мариядб, даже не самая последняя. 1 Надіслати Поділитися на інших сайтах More sharing options... Yoda Опубліковано: 17 грудня 2019 Share Опубліковано: 17 грудня 2019 16 минут назад, 100napb сказал: Спасибо большое за отклик и пример. Больше всего надеялся именно на Ваш ответ. Показать контент к сожалению а) у меня нет под рукой базы с таким количество реальных товаров. Но ради быстрого теста размножил имеющиеся, сохранив необходимую уникальность. б) аналогично Вашему примеру упростим запрос SELECT SQL_NO_CACHE COUNT(*) AS qty FROM product_; Запрос открыт за 0,039c [0,031c выполнение, 0,008c выборка] 1 строк выбрано qty --------------------- 2518592 SELECT SQL_NO_CACHE p.product_id FROM product_ p ORDER BY p.sort_order, p.name LIMIT 0,60; Запрос открыт за 0,048c [0,034c выполнение, 0,014c выборка] 60 строк выбрано product_id ----------- 3797248 3797247 3796136 ... без сфинкса, коробочная мариядб, даже не самая последняя. А толку от него. sql запросы ограничены, просто взять и взять пихнуть в индекс базу не выйдет. Конфликтов с любым дополнением не оберешься. Любой фильтр в целом на категории до 5к товаров настраивается и с mysql базой. Как и любой магазин до 200-300к. Менять архитектуру хранилища, жертвуя совместимостью имеет смысл только в очень специфических случаях, когда вы будете уверены, что в любой момент сможете помочь клиенту со сторонними расширенями. Проблемы с индексацией начинаются где-то с 100к товаров, и зачастую их решение - это какие то не то что костыли а КОСТЫЛЮГИ! Чтобы подружить любой фильтр - надо как минимум написать самому фильтр. Поэтому там где не надо 50к товаров в одной категории, разворачивать сфинкс под каталог - это просто садить на иглу потенциального заказчика. Намного утилитарней, проще и эффективнее, сделать сводные таблицы (исключив лишние джоины) и расставить правильный порядок таблиц в запросе, как в фильтре у маэстро @SooR, так как в итоге это решение, в котором может разобраться любой разработчик. 2 Надіслати Поділитися на інших сайтах More sharing options... Створіть аккаунт або увійдіть для коментування Ви повинні бути користувачем, щоб залишити коментар Створити обліковий запис Зареєструйтеся для отримання облікового запису. Це просто! Зареєструвати аккаунт Вхід Уже зареєстровані? Увійдіть тут. Вхід зараз Share More sharing options... Передплатники 0 Перейти до списку тем Зараз на сторінці 0 користувачів Ні користувачів, які переглядиють цю сторінку Последние темы Последние дополнения Последние новости Вся активність Головна Разное Курилка ускорить sql-запрос из getProducts в /catalog/model/catalog/product.php Покупцям Оплата розширень фізичними особами Оплата розширень юридичними особами Політика повернень Розробникам Регламент розміщення розширень Регламент продажу та підтримки розширень Віртуальний обліковий запис автора Політика просування оголошень API каталогу розширень Вирішення спорів щодо авторських прав Корисна інформація Публічна оферта Політика повернень Політика конфіденційності Платіжна політика Політика передачі особистих даних Політика прозорості Останні розширення PRICE MASTER - Модуль імпорту/експорту товарів, парсинг, переклад, генерація текстів, редактор каталогу та багато іншого Автор: ScriptBrains 1.0 Синхронізація Замовлень Rozetka.ua та Opencart Автор: sinco Product Manipulator Автор: Hiperlynx007 Видалення дублікатів товарів для OpenCart Автор: Hatshypsut Вибір категорій і виробників для "Знайшли дешевше" шаблону Upstore Автор: Flint2000 × Уже зареєстровані? Ввійти Реєстрація Ваші замовлення Назад Придбані модулі та шаблони Ваші рахунки Лист очікувань Альтернативні контакти Форум Новини ocStore Назад Офіційний сайт Демо ocStore 3.0.3.2 Демо ocStore 2.3.0.2.4 Завантажити ocStore Документація Історія версій ocStore Блоги Модулі Шаблони Назад Безкоштовні шаблони Платні шаблони Де купувати модулі? Послуги FAQ OpenCart.Pro Назад Демо Купити Порівняння × Створити... Important Information На нашому сайті використовуються файли cookie і відбувається обробка деяких персональних даних користувачів, щоб поліпшити користувальницький інтерфейс. Щоб дізнатися для чого і які персональні дані ми обробляємо перейдіть за посиланням . Якщо Ви натиснете «Я даю згоду», це означає, що Ви розумієте і приймаєте всі умови, зазначені в цьому Повідомленні про конфіденційність. Я даю згоду
100napb Опубліковано: 20 жовтня 2019 Автор Share Опубліковано: 20 жовтня 2019 (змінено) 2 hours ago, chukcha said: . понял о чем Вы. Респект за внимательность. Действительно, предложенный выше вариант не учитывал случая наличия конкурентных скидок или акций и не мог однозначно определить приоритетную (итоговую) цену. Виноват. Проглядел. Редкий кейс. Но запрос легко исправляется без каких-либо потерей в скорости (проверил). В спойлер ниже закинул и выделил цветом строки, которые решают этот недочет. Spoiler SELECT SQL_NO_CACHE p.product_id, rating.total AS rating, MIN(pd2.price) AS discount, MIN(ps.price) AS special FROM oc_product_to_category p2c 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) LEFT JOIN oc_product_special ps ON (p.product_id = ps.product_id AND ps.priority = (SELECT MIN(priority) FROM oc_product_special WHERE product_id = p.product_id AND customer_group_id = '1' AND ((date_start = '0000-00-00' OR date_start < NOW()) AND (date_end = '0000-00-00' OR date_end > NOW()))) AND customer_group_id = '1' AND ((ps.date_start = '0000-00-00' OR ps.date_start < NOW()) AND (ps.date_end = '0000-00-00' OR ps.date_end > NOW()))) LEFT JOIN oc_product_discount pd2 ON (pd2.product_id = p.product_id AND ps.priority = (SELECT MIN(priority) FROM oc_product_discount WHERE product_id = p.product_id AND customer_group_id = '1' AND ((date_start = '0000-00-00' OR date_start < NOW()) AND (date_end = '0000-00-00' OR date_end > NOW()))) AND pd2.customer_group_id = '1' AND pd2.quantity = '1' AND ((pd2.date_start = '0000-00-00' OR pd2.date_start < NOW()) AND (pd2.date_end = '0000-00-00' OR pd2.date_end > NOW()))) LEFT JOIN (SELECT AVG(rating) AS total, r1.product_id FROM oc_review r1 WHERE r1.status = '1' GROUP BY r1.product_id) AS rating ON p.product_id = rating.product_id WHERE pd.language_id = '1' AND p.status = '1' AND p.date_available <= NOW() AND p2s.store_id = '0' -- AND p2c.category_id = '37' GROUP BY p.product_id ORDER BY p.sort_order ASC, LCASE(pd.name) ASC LIMIT 0, 12 Змінено 20 жовтня 2019 користувачем 100napb Надіслати Поділитися на інших сайтах More sharing options... chukcha Опубліковано: 20 жовтня 2019 Share Опубліковано: 20 жовтня 2019 Я вам поведаю тайну что min и max не очень шустрые.. Все равно в getProduct эти подзапросы существуют А вот тут-то .. не хочу утверждать.. Не проверял, не знаю, но по оракл-опыту getProducts 1.SELECT *, sub_query getProduct 2.SELECT *, sub_query то если код sub_query одинаков до символа, то он будет закеширован и представлен в байткод на момент сессии коннекта. Надіслати Поділитися на інших сайтах More sharing options... 100napb Опубліковано: 20 жовтня 2019 Автор Share Опубліковано: 20 жовтня 2019 (змінено) 18 minutes ago, chukcha said: что min и max не очень шустрые.. все относительно. 1) тут им предстоит определить минимум для небольшого набора значений. очень небольшого 2) я действительно перепроверил результаты из стартового поста. Они актуальные с обновленным запросом Spoiler нативный запрос модифицированный запрос активный товар - этот тот, у которого p.status = 1, т.е. включенная карточка для 100 активных товаров: ~ 0.04сек; (0.04сек) для 6к активных товаров: ~0.4сек (0.2сек) для 19к активных товаров: ~ 2.1сек (0.6сек) для 33к активных товаров: ~2.3сек (1.3сек) для 100к активных товаров: ~7.1 сек (1.5сек) 18 minutes ago, chukcha said: то если код sub_query одинаков до символа, то он будет закеширован и представлен в байткод на момент сессии коннекта. тут, в мускуле\марии, проще и такой проблемы не случится. кэширование подзапросов действует только в рамках одного родительского запроса. на другие не распространяется. За эту оптимизацию отвечает параметр optimizer_switch='subquery_cache=OFF'. Гуглится легко. Строго говоря, мысль была простая: уйти от дорогих зависимых подзапросов в сторону более оптимизированных джоинов. И пока, вроде как, идея жизнеспособна ) Спасибо за замечания. Змінено 20 жовтня 2019 користувачем 100napb погуглил сам))) кажется, кэширование подзапросов - это фича только mariadb Надіслати Поділитися на інших сайтах More sharing options... 1 month later... 100napb Опубліковано: 16 грудня 2019 Автор Share Опубліковано: 16 грудня 2019 Уважаемые, а есть у кого-нибудь опыт\результаты по скорости выполнения запроса из getProducts, если основным хранилищем данных для него будет Sphinx, а не mysql ? А то я тут еще ускорил и стало интересно, а насколько сфинкс круче. Если не сложно, укажите исходное количество товаров для выборки(товаров в категории) и время получения результата с хотя бы "нативной" сортировкой по sort_order и name Надіслати Поділитися на інших сайтах More sharing options... Yoda Опубліковано: 17 грудня 2019 Share Опубліковано: 17 грудня 2019 В 16.12.2019 в 09:16, 100napb сказал: Уважаемые, а есть у кого-нибудь опыт\результаты по скорости выполнения запроса из getProducts, если основным хранилищем данных для него будет Sphinx, а не mysql ? А то я тут еще ускорил и стало интересно, а насколько сфинкс круче. Если не сложно, укажите исходное количество товаров для выборки(товаров в категории) и время получения результата с хотя бы "нативной" сортировкой по sort_order и name mysql> SELECT COUNT(*) as qty FROM product; +---------+ | qty | +---------+ | 1871817 | +---------+ 1 row in set (0.02 sec) mysql> SELECT id FROM main ORDER BY name DESC; +---------+ | id | +---------+ | 5989213 | | 6091563 | | 4350213 | | 4350196 | | 4350195 | | 4350197 | | 4350194 | | 4350192 | | 4350191 | | 4350193 | | 4350190 | | 4350217 | | 4350216 | | 5827378 | | 5827377 | | 5827376 | | 5827375 | | 5827374 | | 5827373 | | 5827372 | +---------+ 20 rows in set (0.16 sec) Но у вас так не получится! Сфинкс не всем раскрывает свои загадки! 2 Надіслати Поділитися на інших сайтах More sharing options... 100napb Опубліковано: 17 грудня 2019 Автор Share Опубліковано: 17 грудня 2019 3 hours ago, Yoda said: Но у вас так не получится! Сфинкс не всем раскрывает свои загадки! Спасибо большое за отклик и пример. Больше всего надеялся именно на Ваш ответ. Spoiler к сожалению а) у меня нет под рукой базы с таким количество реальных товаров. Но ради быстрого теста размножил имеющиеся, сохранив необходимую уникальность. б) аналогично Вашему примеру упростим запрос SELECT SQL_NO_CACHE COUNT(*) AS qty FROM product_; Запрос открыт за 0,039c [0,031c выполнение, 0,008c выборка] 1 строк выбрано qty --------------------- 2518592 SELECT SQL_NO_CACHE p.product_id FROM product_ p ORDER BY p.sort_order, p.name LIMIT 0,60; Запрос открыт за 0,048c [0,034c выполнение, 0,014c выборка] 60 строк выбрано product_id ----------- 3797248 3797247 3796136 ... без сфинкса, коробочная мариядб, даже не самая последняя. 1 Надіслати Поділитися на інших сайтах More sharing options... Yoda Опубліковано: 17 грудня 2019 Share Опубліковано: 17 грудня 2019 16 минут назад, 100napb сказал: Спасибо большое за отклик и пример. Больше всего надеялся именно на Ваш ответ. Показать контент к сожалению а) у меня нет под рукой базы с таким количество реальных товаров. Но ради быстрого теста размножил имеющиеся, сохранив необходимую уникальность. б) аналогично Вашему примеру упростим запрос SELECT SQL_NO_CACHE COUNT(*) AS qty FROM product_; Запрос открыт за 0,039c [0,031c выполнение, 0,008c выборка] 1 строк выбрано qty --------------------- 2518592 SELECT SQL_NO_CACHE p.product_id FROM product_ p ORDER BY p.sort_order, p.name LIMIT 0,60; Запрос открыт за 0,048c [0,034c выполнение, 0,014c выборка] 60 строк выбрано product_id ----------- 3797248 3797247 3796136 ... без сфинкса, коробочная мариядб, даже не самая последняя. А толку от него. sql запросы ограничены, просто взять и взять пихнуть в индекс базу не выйдет. Конфликтов с любым дополнением не оберешься. Любой фильтр в целом на категории до 5к товаров настраивается и с mysql базой. Как и любой магазин до 200-300к. Менять архитектуру хранилища, жертвуя совместимостью имеет смысл только в очень специфических случаях, когда вы будете уверены, что в любой момент сможете помочь клиенту со сторонними расширенями. Проблемы с индексацией начинаются где-то с 100к товаров, и зачастую их решение - это какие то не то что костыли а КОСТЫЛЮГИ! Чтобы подружить любой фильтр - надо как минимум написать самому фильтр. Поэтому там где не надо 50к товаров в одной категории, разворачивать сфинкс под каталог - это просто садить на иглу потенциального заказчика. Намного утилитарней, проще и эффективнее, сделать сводные таблицы (исключив лишние джоины) и расставить правильный порядок таблиц в запросе, как в фильтре у маэстро @SooR, так как в итоге это решение, в котором может разобраться любой разработчик. 2 Надіслати Поділитися на інших сайтах More sharing options... Створіть аккаунт або увійдіть для коментування Ви повинні бути користувачем, щоб залишити коментар Створити обліковий запис Зареєструйтеся для отримання облікового запису. Це просто! Зареєструвати аккаунт Вхід Уже зареєстровані? Увійдіть тут. Вхід зараз Share More sharing options... Передплатники 0 Перейти до списку тем Зараз на сторінці 0 користувачів Ні користувачів, які переглядиють цю сторінку Последние темы Последние дополнения Последние новости Вся активність Головна Разное Курилка ускорить sql-запрос из getProducts в /catalog/model/catalog/product.php Покупцям Оплата розширень фізичними особами Оплата розширень юридичними особами Політика повернень Розробникам Регламент розміщення розширень Регламент продажу та підтримки розширень Віртуальний обліковий запис автора Політика просування оголошень API каталогу розширень Вирішення спорів щодо авторських прав Корисна інформація Публічна оферта Політика повернень Політика конфіденційності Платіжна політика Політика передачі особистих даних Політика прозорості Останні розширення PRICE MASTER - Модуль імпорту/експорту товарів, парсинг, переклад, генерація текстів, редактор каталогу та багато іншого Автор: ScriptBrains 1.0 Синхронізація Замовлень Rozetka.ua та Opencart Автор: sinco Product Manipulator Автор: Hiperlynx007 Видалення дублікатів товарів для OpenCart Автор: Hatshypsut Вибір категорій і виробників для "Знайшли дешевше" шаблону Upstore Автор: Flint2000 × Уже зареєстровані? Ввійти Реєстрація Ваші замовлення Назад Придбані модулі та шаблони Ваші рахунки Лист очікувань Альтернативні контакти Форум Новини ocStore Назад Офіційний сайт Демо ocStore 3.0.3.2 Демо ocStore 2.3.0.2.4 Завантажити ocStore Документація Історія версій ocStore Блоги Модулі Шаблони Назад Безкоштовні шаблони Платні шаблони Де купувати модулі? Послуги FAQ OpenCart.Pro Назад Демо Купити Порівняння × Створити... Important Information На нашому сайті використовуються файли cookie і відбувається обробка деяких персональних даних користувачів, щоб поліпшити користувальницький інтерфейс. Щоб дізнатися для чого і які персональні дані ми обробляємо перейдіть за посиланням . Якщо Ви натиснете «Я даю згоду», це означає, що Ви розумієте і приймаєте всі умови, зазначені в цьому Повідомленні про конфіденційність. Я даю згоду
chukcha Опубліковано: 20 жовтня 2019 Share Опубліковано: 20 жовтня 2019 Я вам поведаю тайну что min и max не очень шустрые.. Все равно в getProduct эти подзапросы существуют А вот тут-то .. не хочу утверждать.. Не проверял, не знаю, но по оракл-опыту getProducts 1.SELECT *, sub_query getProduct 2.SELECT *, sub_query то если код sub_query одинаков до символа, то он будет закеширован и представлен в байткод на момент сессии коннекта. Надіслати Поділитися на інших сайтах More sharing options... 100napb Опубліковано: 20 жовтня 2019 Автор Share Опубліковано: 20 жовтня 2019 (змінено) 18 minutes ago, chukcha said: что min и max не очень шустрые.. все относительно. 1) тут им предстоит определить минимум для небольшого набора значений. очень небольшого 2) я действительно перепроверил результаты из стартового поста. Они актуальные с обновленным запросом Spoiler нативный запрос модифицированный запрос активный товар - этот тот, у которого p.status = 1, т.е. включенная карточка для 100 активных товаров: ~ 0.04сек; (0.04сек) для 6к активных товаров: ~0.4сек (0.2сек) для 19к активных товаров: ~ 2.1сек (0.6сек) для 33к активных товаров: ~2.3сек (1.3сек) для 100к активных товаров: ~7.1 сек (1.5сек) 18 minutes ago, chukcha said: то если код sub_query одинаков до символа, то он будет закеширован и представлен в байткод на момент сессии коннекта. тут, в мускуле\марии, проще и такой проблемы не случится. кэширование подзапросов действует только в рамках одного родительского запроса. на другие не распространяется. За эту оптимизацию отвечает параметр optimizer_switch='subquery_cache=OFF'. Гуглится легко. Строго говоря, мысль была простая: уйти от дорогих зависимых подзапросов в сторону более оптимизированных джоинов. И пока, вроде как, идея жизнеспособна ) Спасибо за замечания. Змінено 20 жовтня 2019 користувачем 100napb погуглил сам))) кажется, кэширование подзапросов - это фича только mariadb Надіслати Поділитися на інших сайтах More sharing options... 1 month later... 100napb Опубліковано: 16 грудня 2019 Автор Share Опубліковано: 16 грудня 2019 Уважаемые, а есть у кого-нибудь опыт\результаты по скорости выполнения запроса из getProducts, если основным хранилищем данных для него будет Sphinx, а не mysql ? А то я тут еще ускорил и стало интересно, а насколько сфинкс круче. Если не сложно, укажите исходное количество товаров для выборки(товаров в категории) и время получения результата с хотя бы "нативной" сортировкой по sort_order и name Надіслати Поділитися на інших сайтах More sharing options... Yoda Опубліковано: 17 грудня 2019 Share Опубліковано: 17 грудня 2019 В 16.12.2019 в 09:16, 100napb сказал: Уважаемые, а есть у кого-нибудь опыт\результаты по скорости выполнения запроса из getProducts, если основным хранилищем данных для него будет Sphinx, а не mysql ? А то я тут еще ускорил и стало интересно, а насколько сфинкс круче. Если не сложно, укажите исходное количество товаров для выборки(товаров в категории) и время получения результата с хотя бы "нативной" сортировкой по sort_order и name mysql> SELECT COUNT(*) as qty FROM product; +---------+ | qty | +---------+ | 1871817 | +---------+ 1 row in set (0.02 sec) mysql> SELECT id FROM main ORDER BY name DESC; +---------+ | id | +---------+ | 5989213 | | 6091563 | | 4350213 | | 4350196 | | 4350195 | | 4350197 | | 4350194 | | 4350192 | | 4350191 | | 4350193 | | 4350190 | | 4350217 | | 4350216 | | 5827378 | | 5827377 | | 5827376 | | 5827375 | | 5827374 | | 5827373 | | 5827372 | +---------+ 20 rows in set (0.16 sec) Но у вас так не получится! Сфинкс не всем раскрывает свои загадки! 2 Надіслати Поділитися на інших сайтах More sharing options... 100napb Опубліковано: 17 грудня 2019 Автор Share Опубліковано: 17 грудня 2019 3 hours ago, Yoda said: Но у вас так не получится! Сфинкс не всем раскрывает свои загадки! Спасибо большое за отклик и пример. Больше всего надеялся именно на Ваш ответ. Spoiler к сожалению а) у меня нет под рукой базы с таким количество реальных товаров. Но ради быстрого теста размножил имеющиеся, сохранив необходимую уникальность. б) аналогично Вашему примеру упростим запрос SELECT SQL_NO_CACHE COUNT(*) AS qty FROM product_; Запрос открыт за 0,039c [0,031c выполнение, 0,008c выборка] 1 строк выбрано qty --------------------- 2518592 SELECT SQL_NO_CACHE p.product_id FROM product_ p ORDER BY p.sort_order, p.name LIMIT 0,60; Запрос открыт за 0,048c [0,034c выполнение, 0,014c выборка] 60 строк выбрано product_id ----------- 3797248 3797247 3796136 ... без сфинкса, коробочная мариядб, даже не самая последняя. 1 Надіслати Поділитися на інших сайтах More sharing options... Yoda Опубліковано: 17 грудня 2019 Share Опубліковано: 17 грудня 2019 16 минут назад, 100napb сказал: Спасибо большое за отклик и пример. Больше всего надеялся именно на Ваш ответ. Показать контент к сожалению а) у меня нет под рукой базы с таким количество реальных товаров. Но ради быстрого теста размножил имеющиеся, сохранив необходимую уникальность. б) аналогично Вашему примеру упростим запрос SELECT SQL_NO_CACHE COUNT(*) AS qty FROM product_; Запрос открыт за 0,039c [0,031c выполнение, 0,008c выборка] 1 строк выбрано qty --------------------- 2518592 SELECT SQL_NO_CACHE p.product_id FROM product_ p ORDER BY p.sort_order, p.name LIMIT 0,60; Запрос открыт за 0,048c [0,034c выполнение, 0,014c выборка] 60 строк выбрано product_id ----------- 3797248 3797247 3796136 ... без сфинкса, коробочная мариядб, даже не самая последняя. А толку от него. sql запросы ограничены, просто взять и взять пихнуть в индекс базу не выйдет. Конфликтов с любым дополнением не оберешься. Любой фильтр в целом на категории до 5к товаров настраивается и с mysql базой. Как и любой магазин до 200-300к. Менять архитектуру хранилища, жертвуя совместимостью имеет смысл только в очень специфических случаях, когда вы будете уверены, что в любой момент сможете помочь клиенту со сторонними расширенями. Проблемы с индексацией начинаются где-то с 100к товаров, и зачастую их решение - это какие то не то что костыли а КОСТЫЛЮГИ! Чтобы подружить любой фильтр - надо как минимум написать самому фильтр. Поэтому там где не надо 50к товаров в одной категории, разворачивать сфинкс под каталог - это просто садить на иглу потенциального заказчика. Намного утилитарней, проще и эффективнее, сделать сводные таблицы (исключив лишние джоины) и расставить правильный порядок таблиц в запросе, как в фильтре у маэстро @SooR, так как в итоге это решение, в котором может разобраться любой разработчик. 2 Надіслати Поділитися на інших сайтах More sharing options... Створіть аккаунт або увійдіть для коментування Ви повинні бути користувачем, щоб залишити коментар Створити обліковий запис Зареєструйтеся для отримання облікового запису. Це просто! Зареєструвати аккаунт Вхід Уже зареєстровані? Увійдіть тут. Вхід зараз Share More sharing options... Передплатники 0 Перейти до списку тем Зараз на сторінці 0 користувачів Ні користувачів, які переглядиють цю сторінку Последние темы Последние дополнения Последние новости Вся активність Головна Разное Курилка ускорить sql-запрос из getProducts в /catalog/model/catalog/product.php Покупцям Оплата розширень фізичними особами Оплата розширень юридичними особами Політика повернень Розробникам Регламент розміщення розширень Регламент продажу та підтримки розширень Віртуальний обліковий запис автора Політика просування оголошень API каталогу розширень Вирішення спорів щодо авторських прав Корисна інформація Публічна оферта Політика повернень Політика конфіденційності Платіжна політика Політика передачі особистих даних Політика прозорості Останні розширення PRICE MASTER - Модуль імпорту/експорту товарів, парсинг, переклад, генерація текстів, редактор каталогу та багато іншого Автор: ScriptBrains 1.0 Синхронізація Замовлень Rozetka.ua та Opencart Автор: sinco Product Manipulator Автор: Hiperlynx007 Видалення дублікатів товарів для OpenCart Автор: Hatshypsut Вибір категорій і виробників для "Знайшли дешевше" шаблону Upstore Автор: Flint2000
100napb Опубліковано: 20 жовтня 2019 Автор Share Опубліковано: 20 жовтня 2019 (змінено) 18 minutes ago, chukcha said: что min и max не очень шустрые.. все относительно. 1) тут им предстоит определить минимум для небольшого набора значений. очень небольшого 2) я действительно перепроверил результаты из стартового поста. Они актуальные с обновленным запросом Spoiler нативный запрос модифицированный запрос активный товар - этот тот, у которого p.status = 1, т.е. включенная карточка для 100 активных товаров: ~ 0.04сек; (0.04сек) для 6к активных товаров: ~0.4сек (0.2сек) для 19к активных товаров: ~ 2.1сек (0.6сек) для 33к активных товаров: ~2.3сек (1.3сек) для 100к активных товаров: ~7.1 сек (1.5сек) 18 minutes ago, chukcha said: то если код sub_query одинаков до символа, то он будет закеширован и представлен в байткод на момент сессии коннекта. тут, в мускуле\марии, проще и такой проблемы не случится. кэширование подзапросов действует только в рамках одного родительского запроса. на другие не распространяется. За эту оптимизацию отвечает параметр optimizer_switch='subquery_cache=OFF'. Гуглится легко. Строго говоря, мысль была простая: уйти от дорогих зависимых подзапросов в сторону более оптимизированных джоинов. И пока, вроде как, идея жизнеспособна ) Спасибо за замечания. Змінено 20 жовтня 2019 користувачем 100napb погуглил сам))) кажется, кэширование подзапросов - это фича только mariadb Надіслати Поділитися на інших сайтах More sharing options... 1 month later... 100napb Опубліковано: 16 грудня 2019 Автор Share Опубліковано: 16 грудня 2019 Уважаемые, а есть у кого-нибудь опыт\результаты по скорости выполнения запроса из getProducts, если основным хранилищем данных для него будет Sphinx, а не mysql ? А то я тут еще ускорил и стало интересно, а насколько сфинкс круче. Если не сложно, укажите исходное количество товаров для выборки(товаров в категории) и время получения результата с хотя бы "нативной" сортировкой по sort_order и name Надіслати Поділитися на інших сайтах More sharing options... Yoda Опубліковано: 17 грудня 2019 Share Опубліковано: 17 грудня 2019 В 16.12.2019 в 09:16, 100napb сказал: Уважаемые, а есть у кого-нибудь опыт\результаты по скорости выполнения запроса из getProducts, если основным хранилищем данных для него будет Sphinx, а не mysql ? А то я тут еще ускорил и стало интересно, а насколько сфинкс круче. Если не сложно, укажите исходное количество товаров для выборки(товаров в категории) и время получения результата с хотя бы "нативной" сортировкой по sort_order и name mysql> SELECT COUNT(*) as qty FROM product; +---------+ | qty | +---------+ | 1871817 | +---------+ 1 row in set (0.02 sec) mysql> SELECT id FROM main ORDER BY name DESC; +---------+ | id | +---------+ | 5989213 | | 6091563 | | 4350213 | | 4350196 | | 4350195 | | 4350197 | | 4350194 | | 4350192 | | 4350191 | | 4350193 | | 4350190 | | 4350217 | | 4350216 | | 5827378 | | 5827377 | | 5827376 | | 5827375 | | 5827374 | | 5827373 | | 5827372 | +---------+ 20 rows in set (0.16 sec) Но у вас так не получится! Сфинкс не всем раскрывает свои загадки! 2 Надіслати Поділитися на інших сайтах More sharing options... 100napb Опубліковано: 17 грудня 2019 Автор Share Опубліковано: 17 грудня 2019 3 hours ago, Yoda said: Но у вас так не получится! Сфинкс не всем раскрывает свои загадки! Спасибо большое за отклик и пример. Больше всего надеялся именно на Ваш ответ. Spoiler к сожалению а) у меня нет под рукой базы с таким количество реальных товаров. Но ради быстрого теста размножил имеющиеся, сохранив необходимую уникальность. б) аналогично Вашему примеру упростим запрос SELECT SQL_NO_CACHE COUNT(*) AS qty FROM product_; Запрос открыт за 0,039c [0,031c выполнение, 0,008c выборка] 1 строк выбрано qty --------------------- 2518592 SELECT SQL_NO_CACHE p.product_id FROM product_ p ORDER BY p.sort_order, p.name LIMIT 0,60; Запрос открыт за 0,048c [0,034c выполнение, 0,014c выборка] 60 строк выбрано product_id ----------- 3797248 3797247 3796136 ... без сфинкса, коробочная мариядб, даже не самая последняя. 1 Надіслати Поділитися на інших сайтах More sharing options... Yoda Опубліковано: 17 грудня 2019 Share Опубліковано: 17 грудня 2019 16 минут назад, 100napb сказал: Спасибо большое за отклик и пример. Больше всего надеялся именно на Ваш ответ. Показать контент к сожалению а) у меня нет под рукой базы с таким количество реальных товаров. Но ради быстрого теста размножил имеющиеся, сохранив необходимую уникальность. б) аналогично Вашему примеру упростим запрос SELECT SQL_NO_CACHE COUNT(*) AS qty FROM product_; Запрос открыт за 0,039c [0,031c выполнение, 0,008c выборка] 1 строк выбрано qty --------------------- 2518592 SELECT SQL_NO_CACHE p.product_id FROM product_ p ORDER BY p.sort_order, p.name LIMIT 0,60; Запрос открыт за 0,048c [0,034c выполнение, 0,014c выборка] 60 строк выбрано product_id ----------- 3797248 3797247 3796136 ... без сфинкса, коробочная мариядб, даже не самая последняя. А толку от него. sql запросы ограничены, просто взять и взять пихнуть в индекс базу не выйдет. Конфликтов с любым дополнением не оберешься. Любой фильтр в целом на категории до 5к товаров настраивается и с mysql базой. Как и любой магазин до 200-300к. Менять архитектуру хранилища, жертвуя совместимостью имеет смысл только в очень специфических случаях, когда вы будете уверены, что в любой момент сможете помочь клиенту со сторонними расширенями. Проблемы с индексацией начинаются где-то с 100к товаров, и зачастую их решение - это какие то не то что костыли а КОСТЫЛЮГИ! Чтобы подружить любой фильтр - надо как минимум написать самому фильтр. Поэтому там где не надо 50к товаров в одной категории, разворачивать сфинкс под каталог - это просто садить на иглу потенциального заказчика. Намного утилитарней, проще и эффективнее, сделать сводные таблицы (исключив лишние джоины) и расставить правильный порядок таблиц в запросе, как в фильтре у маэстро @SooR, так как в итоге это решение, в котором может разобраться любой разработчик. 2 Надіслати Поділитися на інших сайтах More sharing options... Створіть аккаунт або увійдіть для коментування Ви повинні бути користувачем, щоб залишити коментар Створити обліковий запис Зареєструйтеся для отримання облікового запису. Це просто! Зареєструвати аккаунт Вхід Уже зареєстровані? Увійдіть тут. Вхід зараз Share More sharing options... Передплатники 0 Перейти до списку тем Зараз на сторінці 0 користувачів Ні користувачів, які переглядиють цю сторінку Последние темы Последние дополнения Последние новости Вся активність Головна Разное Курилка ускорить sql-запрос из getProducts в /catalog/model/catalog/product.php
100napb Опубліковано: 16 грудня 2019 Автор Share Опубліковано: 16 грудня 2019 Уважаемые, а есть у кого-нибудь опыт\результаты по скорости выполнения запроса из getProducts, если основным хранилищем данных для него будет Sphinx, а не mysql ? А то я тут еще ускорил и стало интересно, а насколько сфинкс круче. Если не сложно, укажите исходное количество товаров для выборки(товаров в категории) и время получения результата с хотя бы "нативной" сортировкой по sort_order и name Надіслати Поділитися на інших сайтах More sharing options... Yoda Опубліковано: 17 грудня 2019 Share Опубліковано: 17 грудня 2019 В 16.12.2019 в 09:16, 100napb сказал: Уважаемые, а есть у кого-нибудь опыт\результаты по скорости выполнения запроса из getProducts, если основным хранилищем данных для него будет Sphinx, а не mysql ? А то я тут еще ускорил и стало интересно, а насколько сфинкс круче. Если не сложно, укажите исходное количество товаров для выборки(товаров в категории) и время получения результата с хотя бы "нативной" сортировкой по sort_order и name mysql> SELECT COUNT(*) as qty FROM product; +---------+ | qty | +---------+ | 1871817 | +---------+ 1 row in set (0.02 sec) mysql> SELECT id FROM main ORDER BY name DESC; +---------+ | id | +---------+ | 5989213 | | 6091563 | | 4350213 | | 4350196 | | 4350195 | | 4350197 | | 4350194 | | 4350192 | | 4350191 | | 4350193 | | 4350190 | | 4350217 | | 4350216 | | 5827378 | | 5827377 | | 5827376 | | 5827375 | | 5827374 | | 5827373 | | 5827372 | +---------+ 20 rows in set (0.16 sec) Но у вас так не получится! Сфинкс не всем раскрывает свои загадки! 2 Надіслати Поділитися на інших сайтах More sharing options... 100napb Опубліковано: 17 грудня 2019 Автор Share Опубліковано: 17 грудня 2019 3 hours ago, Yoda said: Но у вас так не получится! Сфинкс не всем раскрывает свои загадки! Спасибо большое за отклик и пример. Больше всего надеялся именно на Ваш ответ. Spoiler к сожалению а) у меня нет под рукой базы с таким количество реальных товаров. Но ради быстрого теста размножил имеющиеся, сохранив необходимую уникальность. б) аналогично Вашему примеру упростим запрос SELECT SQL_NO_CACHE COUNT(*) AS qty FROM product_; Запрос открыт за 0,039c [0,031c выполнение, 0,008c выборка] 1 строк выбрано qty --------------------- 2518592 SELECT SQL_NO_CACHE p.product_id FROM product_ p ORDER BY p.sort_order, p.name LIMIT 0,60; Запрос открыт за 0,048c [0,034c выполнение, 0,014c выборка] 60 строк выбрано product_id ----------- 3797248 3797247 3796136 ... без сфинкса, коробочная мариядб, даже не самая последняя. 1 Надіслати Поділитися на інших сайтах More sharing options... Yoda Опубліковано: 17 грудня 2019 Share Опубліковано: 17 грудня 2019 16 минут назад, 100napb сказал: Спасибо большое за отклик и пример. Больше всего надеялся именно на Ваш ответ. Показать контент к сожалению а) у меня нет под рукой базы с таким количество реальных товаров. Но ради быстрого теста размножил имеющиеся, сохранив необходимую уникальность. б) аналогично Вашему примеру упростим запрос SELECT SQL_NO_CACHE COUNT(*) AS qty FROM product_; Запрос открыт за 0,039c [0,031c выполнение, 0,008c выборка] 1 строк выбрано qty --------------------- 2518592 SELECT SQL_NO_CACHE p.product_id FROM product_ p ORDER BY p.sort_order, p.name LIMIT 0,60; Запрос открыт за 0,048c [0,034c выполнение, 0,014c выборка] 60 строк выбрано product_id ----------- 3797248 3797247 3796136 ... без сфинкса, коробочная мариядб, даже не самая последняя. А толку от него. sql запросы ограничены, просто взять и взять пихнуть в индекс базу не выйдет. Конфликтов с любым дополнением не оберешься. Любой фильтр в целом на категории до 5к товаров настраивается и с mysql базой. Как и любой магазин до 200-300к. Менять архитектуру хранилища, жертвуя совместимостью имеет смысл только в очень специфических случаях, когда вы будете уверены, что в любой момент сможете помочь клиенту со сторонними расширенями. Проблемы с индексацией начинаются где-то с 100к товаров, и зачастую их решение - это какие то не то что костыли а КОСТЫЛЮГИ! Чтобы подружить любой фильтр - надо как минимум написать самому фильтр. Поэтому там где не надо 50к товаров в одной категории, разворачивать сфинкс под каталог - это просто садить на иглу потенциального заказчика. Намного утилитарней, проще и эффективнее, сделать сводные таблицы (исключив лишние джоины) и расставить правильный порядок таблиц в запросе, как в фильтре у маэстро @SooR, так как в итоге это решение, в котором может разобраться любой разработчик. 2 Надіслати Поділитися на інших сайтах More sharing options... Створіть аккаунт або увійдіть для коментування Ви повинні бути користувачем, щоб залишити коментар Створити обліковий запис Зареєструйтеся для отримання облікового запису. Це просто! Зареєструвати аккаунт Вхід Уже зареєстровані? Увійдіть тут. Вхід зараз Share More sharing options... Передплатники 0 Перейти до списку тем Зараз на сторінці 0 користувачів Ні користувачів, які переглядиють цю сторінку
Yoda Опубліковано: 17 грудня 2019 Share Опубліковано: 17 грудня 2019 В 16.12.2019 в 09:16, 100napb сказал: Уважаемые, а есть у кого-нибудь опыт\результаты по скорости выполнения запроса из getProducts, если основным хранилищем данных для него будет Sphinx, а не mysql ? А то я тут еще ускорил и стало интересно, а насколько сфинкс круче. Если не сложно, укажите исходное количество товаров для выборки(товаров в категории) и время получения результата с хотя бы "нативной" сортировкой по sort_order и name mysql> SELECT COUNT(*) as qty FROM product; +---------+ | qty | +---------+ | 1871817 | +---------+ 1 row in set (0.02 sec) mysql> SELECT id FROM main ORDER BY name DESC; +---------+ | id | +---------+ | 5989213 | | 6091563 | | 4350213 | | 4350196 | | 4350195 | | 4350197 | | 4350194 | | 4350192 | | 4350191 | | 4350193 | | 4350190 | | 4350217 | | 4350216 | | 5827378 | | 5827377 | | 5827376 | | 5827375 | | 5827374 | | 5827373 | | 5827372 | +---------+ 20 rows in set (0.16 sec) Но у вас так не получится! Сфинкс не всем раскрывает свои загадки! 2 Надіслати Поділитися на інших сайтах More sharing options...
100napb Опубліковано: 17 грудня 2019 Автор Share Опубліковано: 17 грудня 2019 3 hours ago, Yoda said: Но у вас так не получится! Сфинкс не всем раскрывает свои загадки! Спасибо большое за отклик и пример. Больше всего надеялся именно на Ваш ответ. Spoiler к сожалению а) у меня нет под рукой базы с таким количество реальных товаров. Но ради быстрого теста размножил имеющиеся, сохранив необходимую уникальность. б) аналогично Вашему примеру упростим запрос SELECT SQL_NO_CACHE COUNT(*) AS qty FROM product_; Запрос открыт за 0,039c [0,031c выполнение, 0,008c выборка] 1 строк выбрано qty --------------------- 2518592 SELECT SQL_NO_CACHE p.product_id FROM product_ p ORDER BY p.sort_order, p.name LIMIT 0,60; Запрос открыт за 0,048c [0,034c выполнение, 0,014c выборка] 60 строк выбрано product_id ----------- 3797248 3797247 3796136 ... без сфинкса, коробочная мариядб, даже не самая последняя. 1 Надіслати Поділитися на інших сайтах More sharing options... Yoda Опубліковано: 17 грудня 2019 Share Опубліковано: 17 грудня 2019 16 минут назад, 100napb сказал: Спасибо большое за отклик и пример. Больше всего надеялся именно на Ваш ответ. Показать контент к сожалению а) у меня нет под рукой базы с таким количество реальных товаров. Но ради быстрого теста размножил имеющиеся, сохранив необходимую уникальность. б) аналогично Вашему примеру упростим запрос SELECT SQL_NO_CACHE COUNT(*) AS qty FROM product_; Запрос открыт за 0,039c [0,031c выполнение, 0,008c выборка] 1 строк выбрано qty --------------------- 2518592 SELECT SQL_NO_CACHE p.product_id FROM product_ p ORDER BY p.sort_order, p.name LIMIT 0,60; Запрос открыт за 0,048c [0,034c выполнение, 0,014c выборка] 60 строк выбрано product_id ----------- 3797248 3797247 3796136 ... без сфинкса, коробочная мариядб, даже не самая последняя. А толку от него. sql запросы ограничены, просто взять и взять пихнуть в индекс базу не выйдет. Конфликтов с любым дополнением не оберешься. Любой фильтр в целом на категории до 5к товаров настраивается и с mysql базой. Как и любой магазин до 200-300к. Менять архитектуру хранилища, жертвуя совместимостью имеет смысл только в очень специфических случаях, когда вы будете уверены, что в любой момент сможете помочь клиенту со сторонними расширенями. Проблемы с индексацией начинаются где-то с 100к товаров, и зачастую их решение - это какие то не то что костыли а КОСТЫЛЮГИ! Чтобы подружить любой фильтр - надо как минимум написать самому фильтр. Поэтому там где не надо 50к товаров в одной категории, разворачивать сфинкс под каталог - это просто садить на иглу потенциального заказчика. Намного утилитарней, проще и эффективнее, сделать сводные таблицы (исключив лишние джоины) и расставить правильный порядок таблиц в запросе, как в фильтре у маэстро @SooR, так как в итоге это решение, в котором может разобраться любой разработчик. 2 Надіслати Поділитися на інших сайтах More sharing options... Створіть аккаунт або увійдіть для коментування Ви повинні бути користувачем, щоб залишити коментар Створити обліковий запис Зареєструйтеся для отримання облікового запису. Це просто! Зареєструвати аккаунт Вхід Уже зареєстровані? Увійдіть тут. Вхід зараз Share More sharing options... Передплатники 0
Yoda Опубліковано: 17 грудня 2019 Share Опубліковано: 17 грудня 2019 16 минут назад, 100napb сказал: Спасибо большое за отклик и пример. Больше всего надеялся именно на Ваш ответ. Показать контент к сожалению а) у меня нет под рукой базы с таким количество реальных товаров. Но ради быстрого теста размножил имеющиеся, сохранив необходимую уникальность. б) аналогично Вашему примеру упростим запрос SELECT SQL_NO_CACHE COUNT(*) AS qty FROM product_; Запрос открыт за 0,039c [0,031c выполнение, 0,008c выборка] 1 строк выбрано qty --------------------- 2518592 SELECT SQL_NO_CACHE p.product_id FROM product_ p ORDER BY p.sort_order, p.name LIMIT 0,60; Запрос открыт за 0,048c [0,034c выполнение, 0,014c выборка] 60 строк выбрано product_id ----------- 3797248 3797247 3796136 ... без сфинкса, коробочная мариядб, даже не самая последняя. А толку от него. sql запросы ограничены, просто взять и взять пихнуть в индекс базу не выйдет. Конфликтов с любым дополнением не оберешься. Любой фильтр в целом на категории до 5к товаров настраивается и с mysql базой. Как и любой магазин до 200-300к. Менять архитектуру хранилища, жертвуя совместимостью имеет смысл только в очень специфических случаях, когда вы будете уверены, что в любой момент сможете помочь клиенту со сторонними расширенями. Проблемы с индексацией начинаются где-то с 100к товаров, и зачастую их решение - это какие то не то что костыли а КОСТЫЛЮГИ! Чтобы подружить любой фильтр - надо как минимум написать самому фильтр. Поэтому там где не надо 50к товаров в одной категории, разворачивать сфинкс под каталог - это просто садить на иглу потенциального заказчика. Намного утилитарней, проще и эффективнее, сделать сводные таблицы (исключив лишние джоины) и расставить правильный порядок таблиц в запросе, как в фильтре у маэстро @SooR, так как в итоге это решение, в котором может разобраться любой разработчик. 2 Надіслати Поділитися на інших сайтах More sharing options...
Recommended Posts