Производительность: получить и сгруппировать детали продукта из 5 таблиц в одном запросе вместо кратных? - PullRequest
0 голосов
/ 16 мая 2019

В настоящее время я разрабатываю фоновые cms для интернет-магазина.

Я разбил таблицы в своей базе данных следующим образом:
-произведения
-продукт-детали (descrition ...)
-productimages
Варианты продукции (цвета ..)
кросс-продажи

Теперь на странице редактирования продукта мне нужно получить все данные для одного продукта. Поэтому мой вопрос заключается в том, как сделать эти детали более эффективными, чем совершать 3-5 вызовов в базу данных.

Или обработка с использованием php будет менее эффективной, чем выполнение этих 3-5 вызовов?

На данный момент запрос выглядит так:

SELECT 
        pr.id, pr.categorieid, pr.itemnumber, pr.barcode, pr.price, pr.weight, pr.gender, pr.manufracture, pr.fsk18, pr.condition, pc.id AS pcid, pc.productcrossid, pc.sort, pd.productname, 
        pd.productdesc, pd.additional, pd.linktitle, pd.metatitle, pd.metadesc, pd.urlkeywords, pi.id AS piid, pi.wichimage, pi.variantid, pi.image, pi.imagealt, pv.id AS pvid, pv.variant,
        pv.variantvalue, pv.sku, pv.price AS pvprice, pv.weight AS pvweight, pv.stock, pv.special
    FROM 
        products pr
    LEFT JOIN 
        productcross as pc
        ON pr.id = pc.productid 
    LEFT JOIN 
        productdetails as pd
        ON pr.id = pd.productid     
    LEFT JOIN 
        productimage as pi
        ON pr.id = pi.productid AND pd.lang = pi.lang
    LEFT JOIN 
        productvariants as pv
        ON pr.id = pv.productid
    WHERE 
        pr.id = :id
    ORDER BY pd.lang ASC

В результате я получаю много строк, так как из-за левого соединения каждое значение соединяется со строками, которые я ранее соединял.

Проблема в том, что существует множество строк для перекрестных продаж, вариантов, изображений, поэтому может быть случайным, если вариантов или изображений больше (иначе я мог бы сгруппировать их по крайней мере, потому что каждый вариант может получить свое изображение, но может быть также больше изображений, чем варианты)

Продукты 1 строка, productdetails в зависимости от того, сколько языков используется, наиболее вероятно 3.

Редактировать: Согласно Explain и заданным мною индексам производительность этого отдельного запроса очень хорошая.


Редактировать

По словам Пола Шпигеля, я попробовал использовать GROUP_CONCAT

   SELECT 
        pr.id, pr.categorieid, pr.itemnumber, pr.barcode, pr.price, pr.weight, pr.gender, pr.manufracture, pr.fsk18, pr.condition, pc.id AS pcid, pc.productcrossid, pc.sort, pd.productname, 
        pd.productdesc, pd.additional, pd.linktitle, pd.metatitle, pd.metadesc, pd.urlkeywords
    FROM 
        products pr
    LEFT JOIN 
        productsdetails as pd
        ON pr.id = pd.productid     
    LEFT JOIN (
        SELECT 
        GROUP_CONCAT(productcrossid) AS pcproductcrossid, GROUP_CONCAT(sort) AS pcsort, GROUP_CONCAT(id) AS pcid, productid
        FROM productscross
        WHERE productid = :id
        ) pc 
        ON pr.id = pc.productid 

    WHERE 
        pr.id = :id
    ORDER BY pd.lang ASC

Ответы [ 2 ]

1 голос
/ 19 мая 2019

В результате я получаю много строк, так как при левом соединении каждое значение объединяется со строками, к которым я присоединился ранее.

Это не то, что означает LEFT.

X JOIN Y ON ... доставляет строки, которые отображаются на и X, и Y.
X LEFT JOIN Y ON ... доставляет все строки X, даже если нет соответствующей строки (или строк)) в Y.

Вы можете получить «много строк», потому что отношение «1: много».Подумайте о Classes JOIN Students С JOIN вы получите несколько строк на Class (по одной на каждого учащегося), за исключением для любых классов без учеников.С LEFT JOIN вы дополнительно получаете строку для любого класса без учеников.

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

В EXPLAIN, умножить на числа в столбце «Строки» - это будет грубая метрика того, насколько большим будет набор результатов.

Используйте один запрос для получения изображений;другой, чтобы получить цвета;и т. д. Используйте JOIN (или LEFT JOIN только при необходимости.

GROUP_CONCAT() иногда удобно. Возможно, будет полезно перечислить «цвета». Но для «изображений» вам потребуетсяразделите его так, чтобы можно было создать несколько тегов <img..>. Это довольно легко сделать, но это дополнительная работа.

Обычно «неправильно» иметь отображение 1: 1 между таблицами. В таких случаяхпочему бы не иметь одну таблицу?

Не бойтесь 3-5 запросов. Мы говорим миллисекунды. Рендеринг страницы, вероятно, займет в несколько раз больше, чем SELECTs. У меня часто несколько десятковЗапросы для создания веб-страницы, но я доволен производительностью. И, да, я приписываю идею размещать всю информацию об одном «продукте» на странице сразу (когда это практически возможно). Это гораздо лучше, чем необходимостьнажмите здесь, чтобы получить цвета и нажмите там, чтобы увидеть изображения и т. д.

0 голосов
/ 20 мая 2019

Вместо того, чтобы выполнять так много запросов, вы можете обратиться к концепции, известной как плоские таблицы в magento.

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

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

Для справки. Пожалуйста, проверьте ссылку ниже, надеюсь, это поможет.

Визит http://excellencemagentoblog.com/blog/2015/06/10/magento-flat-tables/

Я знаю, что вопрос не касается Magento, но вы можете создать свою собственную логику для достижения этого механизма.

...