Оптимизировать выбранные данные о товарах, которые каждый покупатель покупал по таблицам продаж - PullRequest
0 голосов
/ 25 января 2019

У меня есть 4 таблицы: клиенты, продукты, продажи и продажа.Я извлекаю данные из него, используя запрос ниже.

SELECT (
            SELECT c.name 
            FROM Customers c
            WHERE s.customer_id=c.id
            ) customer
    ,(
        Select group_concat(description)
        FROM (
            SELECT si.id
                ,si.sale_id
                ,concat("x", si.Qty, " ", p.name, " ",(si.total)) description
            FROM Sale_Items si
            LEFT JOIN Products p ON p.id = si.product_id
            ) p
        where s.id = Sale_ID
        GROUP BY Sale_ID
        ) detail,
                            s.total
FROM Sales s

Запрос выдает результат, но он замедляется только с 2000 записями (для завершения требуется 114 секунд)

Customer    Product            Total
--------------------------------------
James       x1 ItemA 10.00  75.00
            x3 ItemB 15.00
            x1 ItemC 20.00

Mark        x2 ItemA 10.00  50.00
            x2 ItemB 15.00

Bisi        x1 ItemC 20.00  30.00
            x2 ItemA 10.00

какя могу сделать это быстрее?

Здесь была сделана попытка

https://www.db -fiddle.com / f / pkL2HtsT659EXgRSevFSAm / 4

1 Ответ

0 голосов
/ 25 января 2019

Если мы хотим придерживаться коррелированных подзапросов, мы можем исключить встроенное представление p.

Это будет реализовано для каждой строки, извлеченной из Sales.Предикат в предложении WHERE во внешнем запросе не «выталкивается» в представление.Таким образом, материализованное представление (или «производная таблица» на языке MySQL) будет полным набором, и из этого мы выделим всего несколько строк.И мы собираемся повторить это для каждой строки из Sales.

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

SELECT ( SELECT c.name 
           FROM Customers c
          WHERE c.id = s.customer_id
       ) AS customer

     , ( SELECT GROUP_CONCAT(CONCAT('x',si.Qty,' ',p.name,' ',si.total) ORDER BY p.name SEPARATOR '\r\n')
           FROM Sale_Items si
           LEFT
           JOIN Products p
             ON p.id = si.product_id
          WHERE si.sale_id = s.id
       ) AS detail

     , s.total

  FROM Sales s

 WHERE ... 

 ORDER
    BY ...

Если запрос возвращает все строки из Sales и мы выполняем весь набор bloomin 'set, то I'Я стараюсь избегать коррелированных подзапросов.(Это потому, что подзапросы выполняются для каждой строки, возвращаемой внешним запросом. Эти подзапросы будут съедать наш обед с точки зрения производительности с большим количеством возвращаемых строк.)

Предполагая id уникален в customers, нам, как правило, гораздо лучше с операцией соединения.

SELECT c.name AS customer
     , d.detail
     , s.total
  FROM Sales s
  LEFT
  JOIN Customers c
    ON c.id = s.customer_id
  LEFT
  JOIN ( SELECT si.sale_id
              , GROUP_CONCAT(CONCAT('x',si.Qty,' ',p.name,' ',si.total) ORDER BY p.name SEPARATOR '\r\n') AS detail
           FROM Sale_Items si
           LEFT
           JOIN Products p
             ON p.id = si.product_id
          GROUP
             BY si.sale_id
       ) d
    ON d.sale_id = s.id
 ORDER
    BY ...

Встроенное представление d будет дорого с большими наборами;но, по крайней мере, мы делаем этот запрос только один раз, материализуя результаты в «производную таблицу».Затем можно выполнить внешний запрос и извлечь строки из производной таблицы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...