|
Несколько Join таблицы саму на себя
|
|||
---|---|---|---|
#18+
Добрый день, существует 3 таблицы. Таблица product Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18.
Таблица attribute Код: sql 1. 2. 3. 4. 5. 6. 7.
Таблица product_to_attribute Код: sql 1. 2. 3. 4. 5.
В реальности имеем товары, которые содержать несколько атрибутов, 1 и больше. Необходимо получать товары по заданным атрибутам. В качестве реализации использую вот такой запрос: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29.
Если атрибутов до 5, то скорость выполнения приемлема, если 8 и больше, то скорость > 20 cек. В качестве СУБД использую MySQL 5.7.31. Записей в product > 150 000, attribute 600, product_to_attribute > 500 000 и база будет расти. Не могли бы вы подсказать или натолкнуть как правильно оптимизировать скорость выполнения запросов? ... |
|||
:
Нравится:
Не нравится:
|
|||
01.10.2020, 10:56 |
|
Несколько Join таблицы саму на себя
|
|||
---|---|---|---|
#18+
para_bit, 1. Перевести все в InnoDb и даже лучше в xtraDb или как там оно зовется. 2. Навешать правильные ключи. 3. Объединять 1 раз с group by и having с подсчетом кол-ва атрибутов у товара .. в общем, перейти на eav выборки. как-то так. Детальней надо вспоминать .. давно с продольным хранением атрибутов на якшался.. подзабыл ужо. Кстати! Может коллективно вспомнить, обсудить и выложить в фак? Типо "штатная работа с EAV" .. там при правильной готовке запросов снижение скорости от прямых выборок из широких таблиц не превышало 2-3 раз на MySql 5.1.47 .. когда это было .. ;) ... |
|||
:
Нравится:
Не нравится:
|
|||
01.10.2020, 11:15 |
|
Несколько Join таблицы саму на себя
|
|||
---|---|---|---|
#18+
Arhat109, Спасибо за ваш ответ, 1) сейчас работает на MyIsam, насколько я понимаю выборка с этим типом шустрее 2) Индексы и ключе расставлены ... |
|||
:
Нравится:
Не нравится:
|
|||
01.10.2020, 11:50 |
|
Несколько Join таблицы саму на себя
|
|||
---|---|---|---|
#18+
para_bit, В таком разе, что Вы хатите? Раз "все есть и шустрее" .. ;) ... |
|||
:
Нравится:
Не нравится:
|
|||
01.10.2020, 12:08 |
|
Несколько Join таблицы саму на себя
|
|||
---|---|---|---|
#18+
Arhat109, где-то тут, за 2011-2013гг болтается описание того сервака, на котором всё это отрабатывалось, кажется 2 ядра Xeon по 1.9Мгц и 8 гигабайт оперативы. СУБД товаров - 500тыс строк. Атрибутов около 3-15 на товар. Средняя выборка по атрибутам в пределах 0.6сек. как-то так, возможно micsoft ещё помнит.. ;) ... |
|||
:
Нравится:
Не нравится:
|
|||
01.10.2020, 12:10 |
|
Несколько Join таблицы саму на себя
|
|||
---|---|---|---|
#18+
para_bit Необходимо получать товары по заданным атрибутам. В качестве реализации использую вот такой запрос: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29.
ЯНХНП. Запрос кривой. Запятая перед FROM, неизвестная таблица p2c, куча непонятных жойнов, в списке выбора поля, не участвующие в группировке. ... |
|||
:
Нравится:
Не нравится:
|
|||
01.10.2020, 16:44 |
|
Несколько Join таблицы саму на себя
|
|||
---|---|---|---|
#18+
paver, Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28.
спасибо, поправил запрос в этом сообщении, каждый JOIN это поиск по конкретному типу атрибута, 8 Join = 8 типов атрибутов. Про какие вы поля, какие не участвуют в группировке ... |
|||
:
Нравится:
Не нравится:
|
|||
01.10.2020, 17:45 |
|
Несколько Join таблицы саму на себя
|
|||
---|---|---|---|
#18+
para_bit Код: sql 1.
para_bit Код: sql 1.
... |
|||
:
Нравится:
Не нравится:
|
|||
01.10.2020, 23:02 |
|
Несколько Join таблицы саму на себя
|
|||
---|---|---|---|
#18+
Да, мне тоже непонятно. Если это восемь разных групп атрибутов, то атрибут не должен попадаться в разных группах, верно? Иначе это похоже на " синий или красный" + "мелкий или средний" + "гладкий или синий " ... |
|||
:
Нравится:
Не нравится:
|
|||
01.10.2020, 23:37 |
|
Несколько Join таблицы саму на себя
|
|||
---|---|---|---|
#18+
По-моему, эту задачу можно решить одним джойном, если выполняются следующие условия: - все атрибуты делятся на известное число категорий (цвет, размер, производитель) - внутри категории, атрибуты взаимоисключающие (товар не может быть зеленый и желтый одновременно) - из первых двух следует, что у товара не может быть больше атрибутов, чем категорий это также означает, что атрибуты для критерия поиска можно смешать вместе (ищем красный + маленький + китайский) Ниже я привожу пример (правда на Оракле, я с ним работаю), а тут попробую написать сохраняя синтакс ТС Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14.
Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25.
... |
|||
:
Нравится:
Не нравится:
|
|||
02.10.2020, 01:47 |
|
Несколько Join таблицы саму на себя
|
|||
---|---|---|---|
#18+
para_bit Код: sql 1. 2. 3. 4.
Про какие вы поля, какие не участвуют в группировке Группируете по model, а в списке селекта используете product_id. Если между product_id и model имеется взаимно однозначное соответствие, то группировать явно лучше по полю int, а не varchar. Тогда и индекс по model не потребуется ... |
|||
:
Нравится:
Не нравится:
|
|||
02.10.2020, 05:38 |
|
Несколько Join таблицы саму на себя
|
|||
---|---|---|---|
#18+
miksoft, спасибо, вы правы, атрибуты действительно не должны повторяться в рамках одного типа, моя невнимательность. Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28.
... |
|||
:
Нравится:
Не нравится:
|
|||
02.10.2020, 05:53 |
|
Несколько Join таблицы саму на себя
|
|||
---|---|---|---|
#18+
НеофитSQL, Число категорий атрибутов действительно известно, но не все атрибуты взаимоисключающие, так, например изделие может быть: Золотое, 585 пробы, иметь 2 камня Сапфир и Бриллиант, и соответственно несколько цветов камней Фиолетовый и Белый. ... |
|||
:
Нравится:
Не нравится:
|
|||
02.10.2020, 05:58 |
|
Несколько Join таблицы саму на себя
|
|||
---|---|---|---|
#18+
para_bit НеофитSQL, Число категорий атрибутов действительно известно, но не все атрибуты взаимоисключающие, так, например изделие может быть: Золотое, 585 пробы, иметь 2 камня Сапфир и Бриллиант, и соответственно несколько цветов камней Фиолетовый и Белый. Это можно привести к взаимоискчающим атрибутам через увеличение числа категорий (материал, проба, тип камня1, тип камня2,..), но выглядит трудоёмко. Вот ещё одна идея, которую можно попробовать за пару минут: замените все джойны на RIGHT JOIN, оставьте все остальное как было. Я сейчас не у компа, но учитывая просеивающую форму запроса, это по-моему будет то что надо.. ... |
|||
:
Нравится:
Не нравится:
|
|||
02.10.2020, 07:24 |
|
Несколько Join таблицы саму на себя
|
|||
---|---|---|---|
#18+
НеофитSQL замените все джойны на RIGHT JOIN ... |
|||
:
Нравится:
Не нравится:
|
|||
02.10.2020, 08:12 |
|
Несколько Join таблицы саму на себя
|
|||
---|---|---|---|
#18+
НеофитSQL, Спасибо, попробовал, но не помогло, время выполнения прежнее ... |
|||
:
Нравится:
Не нравится:
|
|||
02.10.2020, 08:20 |
|
Несколько Join таблицы саму на себя
|
|||
---|---|---|---|
#18+
Посоветовали пару решений на другом форуме, изложу ниже результаты по ним Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13.
Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.
Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14.
... |
|||
:
Нравится:
Не нравится:
|
|||
02.10.2020, 08:23 |
|
Несколько Join таблицы саму на себя
|
|||
---|---|---|---|
#18+
НеофитSQL, Все верно, примерно так как Вы и дали запрос: там на самом деле пофиг сколько типов атрибутов у товара 8 или иное число. Джойн ровно один, а вот все остальное регулируется в WHERE и HAVING Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18.
При правильно настроенных индексах запросы такого формата работают наиболее оптимальным способом. Вот, по ним и их переработке на оконные функции и предлагаю сделать очередной "фак".. ;) ... |
|||
:
Нравится:
Не нравится:
|
|||
02.10.2020, 08:34 |
|
Несколько Join таблицы саму на себя
|
|||
---|---|---|---|
#18+
В третьем варианте откуда взялась таблица категорий товаров? Если она есть, то да, по ней тоже можно отсеять не нужное. Особенно, если атрибуты - категорированы и список IN() можно делить по ним. ... |
|||
:
Нравится:
Не нравится:
|
|||
02.10.2020, 08:49 |
|
Несколько Join таблицы саму на себя
|
|||
---|---|---|---|
#18+
Arhat109, получился вот такой запрос для 8 параметров Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27.
Время выполнения 0.9107 сек. Таблицу категории да, тоже включил ... |
|||
:
Нравится:
Не нравится:
|
|||
02.10.2020, 10:02 |
|
Несколько Join таблицы саму на себя
|
|||
---|---|---|---|
#18+
para_bit, опишите словами условия в блоке HAVING там у Вас не строгое равенство почему-то. Вы ищете по ИЛИ в такой набор атрибутов ИЛИ из этой группы? ... |
|||
:
Нравится:
Не нравится:
|
|||
02.10.2020, 10:59 |
|
Несколько Join таблицы саму на себя
|
|||
---|---|---|---|
#18+
Arhat109, отбираем товары, у которых: Проба 585 или 750 И Метали Золото или Серебро И размер 17 или 22 или 40 или 50 И Камень Сапфир или Бриллиант И Цвет Фиолетовый или Белый .... В рамках одной группы атрибутов может быть, как одно, так и несколько условий, искать можем, как по 585 и 750, так и просто по 585 Т.е. задаем условие поиска в каталоге товаров ... |
|||
:
Нравится:
Не нравится:
|
|||
02.10.2020, 11:35 |
|
Несколько Join таблицы саму на себя
|
|||
---|---|---|---|
#18+
помоему вы фасеты хотите. ... |
|||
:
Нравится:
Не нравится:
|
|||
02.10.2020, 11:50 |
|
Несколько Join таблицы саму на себя
|
|||
---|---|---|---|
#18+
para_bit, Вот. Значит Вам надо считать не кол-во атрибутов золото оно ИЛИ серебро, а кол-во их категорий есть И Проба И Метали И размер И Камень И Цвет в части HAVING, а по или отбор произойдет в WHERE. Как-то так наверное: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19.
Произведение даст нуль, если хотя бы одна группа отсутствует. ... |
|||
:
Нравится:
Не нравится:
|
|||
02.10.2020, 11:55 |
|
Несколько Join таблицы саму на себя
|
|||
---|---|---|---|
#18+
Кстати, получилось что cntAttr Вам вообще тут не интересен, сколько их нашлось всего. Можно в SELECT воткнуть логическую функцию И то И это .. и в HAVING проверять только ее истинность. Сравните с таким же колвом параметров с другими способами .. уже интересно :) ... |
|||
:
Нравится:
Не нравится:
|
|||
02.10.2020, 11:58 |
|
Несколько Join таблицы саму на себя
|
|||
---|---|---|---|
#18+
ScareCrow, Как понял "не совсем". Фасеты (мож ошибаюсь) это последовательный параметризованный поиск. Выбрали срез - показали (заодно сохранили, урезав выборку) и так постепенно добавляем параметры отбора. Это полноценный параметризованный поиск по параметрам - выбрали набор параметров и жмакнули "и-щи!" получили результом только то что надо. Оба подхода имеют место быть и у каждого свои плюсики, как и минусики, кмк. :) ... |
|||
:
Нравится:
Не нравится:
|
|||
02.10.2020, 12:53 |
|
Несколько Join таблицы саму на себя
|
|||
---|---|---|---|
#18+
даже по вашему описанию разницу не видно. ... |
|||
:
Нравится:
Не нравится:
|
|||
02.10.2020, 13:17 |
|
Несколько Join таблицы саму на себя
|
|||
---|---|---|---|
#18+
ScareCrow, Разница в реализации. В фасете делаем несколько стартовых view с начальным параметром и прячем в кеш (типо для ускорения первичной выборки), а во втором случае сразу прописываем сложный запрос с кучей параметров и получаем весь результ на руки единовременно. Фасетный поиск, как вариант, ещё вместо выборок в кеш сохраняют отдельные профили индексов "типа предвыборка".. в любом разе, это несколько последовательных этапов (запросов) по 1шт на новый параметр на базе предыдущей выборки. .. ну это как делал, как понимаю .. оф. терминология (Вики): ".. Фасетный поиск позволяет перемещаться по многомерному информационному пространству через объединение текстового поиска с постепенным сужением выбора в каждом измерении .." Реализуется на веб странице параметрической формой, где каждый выбор, тут же показывает "нашлось ххх товаров" .. т.е. часть поиска проведена по этому параметру и создана "фасета" (врем. тбл).. То что тут - это одновременная (разовая) выборка по всему комплекту сразу... собственно "вся разница". :) ... |
|||
:
Нравится:
Не нравится:
|
|||
02.10.2020, 13:28 |
|
Несколько Join таблицы саму на себя
|
|||
---|---|---|---|
#18+
ScareCrow, добрый день, я такое из коробки только про Битрикс слышал, я так понимаю, что реализовать это не так просто, подскажите, что почитать? ... |
|||
:
Нравится:
Не нравится:
|
|||
02.10.2020, 13:44 |
|
Несколько Join таблицы саму на себя
|
|||
---|---|---|---|
#18+
Arhat109, не совсем понял о какой логической функции в SELECT вы говорите? Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16.
разбирался с вариантом который вы предложили и правда интересно, но время выполнения 0.9268 сек. т.е. похоже, что доп. условия не влияли на скорость фильтрации ... |
|||
:
Нравится:
Не нравится:
|
|||
02.10.2020, 15:02 |
|
Несколько Join таблицы саму на себя
|
|||
---|---|---|---|
#18+
para_bit, Эта модификация и не должна быть быстрее, разве что очень незначительно, т.к. объем выборки тут не изменен по сравнению в пред. вариантом - группируются теже строки. Тут просто наглядней что суммирование - это вычисление попадания в группы, наличие которых Вы потом требуете в HAVING. Так кмк наглядней что ищется. Меня интересовало сравнение с другими вариантами запросов, что Вы привели раньше, для одних и тех же данных и условий поиска. Особенно с вариантом 3. ... |
|||
:
Нравится:
Не нравится:
|
|||
02.10.2020, 15:48 |
|
Несколько Join таблицы саму на себя
|
|||
---|---|---|---|
#18+
para_bit ScareCrow, добрый день, я такое из коробки только про Битрикс слышал, я так понимаю, что реализовать это не так просто, подскажите, что почитать? штатно это есть в Эластике и Сфинксе. ... |
|||
:
Нравится:
Не нравится:
|
|||
02.10.2020, 16:29 |
|
Несколько Join таблицы саму на себя
|
|||
---|---|---|---|
#18+
Akina НеофитSQL замените все джойны на RIGHT JOIN Этот совет следует логике фасетной фильтрации (я не знал этого термина), которая обсуждалась позже в этой теме. Будучи новичком в SQL, я пока некомфортно отношусь к огромному числу комбинаторных вариантов порожденными inner join восьмой степени. Ошибка в условии WHERE может привести в взрывному (миллионы раз) увеличению числа строк. Right join позволяет мне думать об этой задаче как о последовательной фильтрации таблицы product_attribute, с кардинальностью возможного ответа не превышающего размера product_attribute, и (для меня) более простой отладке в случае ошибки. Я понимаю оптимизатор SQL это умная штука, и может исполнять inner join очень эффективно, несмотря на кажущиеся миллиарды комбинаций в десятой степени. ТС сравнил скорость inner/right join, скорость оказалась одинаковой - это говорит о качестве оптимизатора. Надеюсь, ответил на ваш вопрос. ... |
|||
:
Нравится:
Не нравится:
|
|||
02.10.2020, 18:07 |
|
Несколько Join таблицы саму на себя
|
|||
---|---|---|---|
#18+
Arhat109, Код: sql 1.
ну это как бы одно "яйцо") ... |
|||
:
Нравится:
Не нравится:
|
|||
02.10.2020, 19:42 |
|
Несколько Join таблицы саму на себя
|
|||
---|---|---|---|
#18+
НеофитSQL Надеюсь, ответил на ваш вопрос. Но я навылет не понимаю, где хоть какая-то точка соприкосновения между различиями в логике получения результатов (вернее, каким условиям отвечают записи, различающие наборы для внутреннего и правого связываний) и этим обоснованием. "Скажите, а вы не пробовали мочу молодого поросёнка?" (с) Что же до тутошнего, частного, случая: Код: sql 1. 2. 3. 4.
Продолжать? ... |
|||
:
Нравится:
Не нравится:
|
|||
03.10.2020, 21:14 |
|
Несколько Join таблицы саму на себя
|
|||
---|---|---|---|
#18+
Akina, лол, я как раз вернулся дополнить мое сообщение. меа кулпа. Я позже понял что мое предложение с левым джойн было совершенно бессмысленным, т.к. я неверно о них думал, после нескольких недель левых джойнов по уникальным ключам (там они действительно не увеличивают кардинальность). Досадная ошибка, которую я бы может и не сделал бы днем или месяц назад :) Вот что я надеялся сделать. Привожу несколько строчек от ТС для удобства обсуждения: Код: sql 1. 2. 3.
Начать с таблицы product_to_attribute. Там более полумиллиона строчек. 1) отсеять из связочной таблицы product_to_attribute все товары, у которых нет атрибута 12 или 23. Строчек стало меньше 2) отсеять все товары, у которых нет атрибутов 2, или 37, или 42, или 54, или 1 3) отсеять все товары, у которых нет атрибутов 4 или 38. .. и т.д. Не заменяйте нна лефт джойн, это было неверно. ... |
|||
:
Нравится:
Не нравится:
|
|||
03.10.2020, 22:49 |
|
Несколько Join таблицы саму на себя
|
|||
---|---|---|---|
#18+
НеофитSQL, Разве такое не полностью эквивалентно одному in() с перечислением ВСЕХ идентов атрибутов? И оптимизатор не преобразует такой набор AND в один просмотр? Подозреваю, что преобразует, т.к. на Ix86 наборе команд есть префикс повторения, с помощью которого поиск значения в списке (наборе) делается вовсе "одной командой" .. ну, по крайней мере, соблазн велик. ... |
|||
:
Нравится:
Не нравится:
|
|||
04.10.2020, 05:56 |
|
Несколько Join таблицы саму на себя
|
|||
---|---|---|---|
#18+
Alex_Ustinov, почти. Тут непонятно какая версия мускуля, перконы или марии в пользовании. Ну и ещё вспомнилось (не знаю как сейчас), MyISAM имеет плохое масштабирование к количеству приджойненных табличек и особенно в режимах GROUP BY/HAVING .. я бы все же перешел на другой движок. ... |
|||
:
Нравится:
Не нравится:
|
|||
04.10.2020, 08:19 |
|
Несколько Join таблицы саму на себя
|
|||
---|---|---|---|
#18+
НеофитSQL Начать с таблицы product_to_attribute. Там более полумиллиона строчек. 1) отсеять из связочной таблицы product_to_attribute все товары, у которых нет атрибута 12 или 23. Строчек стало меньше 2) отсеять все товары, у которых нет атрибутов 2, или 37, или 42, или 54, или 1 3) отсеять все товары, у которых нет атрибутов 4 или 38. .. и т.д. "Отсекаем всё лишнее" - это и про SQL. Если же попытаться серверу "помочь", заставив его хитровывернутыми конструкциями делать вот именно так - практически наверняка станет только хуже. ... |
|||
:
Нравится:
Не нравится:
|
|||
04.10.2020, 09:51 |
|
Несколько Join таблицы саму на себя
|
|||
---|---|---|---|
#18+
<dup - del> ... |
|||
:
Нравится:
Не нравится:
|
|||
04.10.2020, 09:51 |
|
Несколько Join таблицы саму на себя
|
|||
---|---|---|---|
#18+
ScareCrow, спасибо, буду разбираться. ... |
|||
:
Нравится:
Не нравится:
|
|||
04.10.2020, 12:43 |
|
Несколько Join таблицы саму на себя
|
|||
---|---|---|---|
#18+
Arhat109 Alex_Ustinov, почти. Тут непонятно какая версия мускуля, перконы или марии в пользовании. Ну и ещё вспомнилось (не знаю как сейчас), MyISAM имеет плохое масштабирование к количеству приджойненных табличек и особенно в режимах GROUP BY/HAVING .. я бы все же перешел на другой движок. версия MySQL указана в первом сообщении 5.7.31. ... |
|||
:
Нравится:
Не нравится:
|
|||
04.10.2020, 12:44 |
|
Несколько Join таблицы саму на себя
|
|||
---|---|---|---|
#18+
para_bit, В таком разе, как понимаю innoDb и xtraDb несколько не одно и тоже.. но пусть меня поправят, если ошибся. ... |
|||
:
Нравится:
Не нравится:
|
|||
04.10.2020, 22:26 |
|
|
start [/forum/topic.php?all=1&fid=47&tid=1828360]: |
0ms |
get settings: |
9ms |
get forum list: |
15ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
56ms |
get topic data: |
9ms |
get forum data: |
2ms |
get page messages: |
78ms |
get tp. blocked users: |
2ms |
others: | 260ms |
total: | 439ms |
0 / 0 |