Оптимизация SQL-запросов - PullRequest
0 голосов
/ 31 марта 2010

У меня проблема с моим запросом SQL, который требует времени для получения всех записей из базы данных. Любое тело поможет мне. Ниже приведен пример базы данных:

order(order_id, order_nm)
customer(customer_id, customer_nm)
orderDetail(orderDetail_id, order_id, orderDate, customer_id, Comment)

Я хочу получить последнюю информацию о клиенте и заказе.
Вот майское решение:

Я создал функцию GetLatestOrderByCustomer (CusID) для получения последней информации о клиентах.

CREATE FUNCTION [dbo].[GetLatestOrderByCustomer]
(
    @cus_id int
)
RETURNS varchar(255)
AS
BEGIN
    DECLARE @ResultVar varchar(255)

    SELECT @ResultVar = tmp.comment
    FROM 
    (
        SELECT TOP 1 orderDate, comment
        FROM orderDetail
        WHERE orderDetail.customer_id = @cust_id
    ) tmp


    -- Return the result of the function
    RETURN @ResultVar

END

Ниже мой SQL-запрос

SELECT 
      customer.customer_id
    , customer.customer_nm
    , dbo.GetLatestOrderByCustomer(customer.customer_id)
FROM Customer
    LEFT JOIN orderDetail
        ON orderDetail.customer_id = customer.customer_id

Требуется время, чтобы запустить функцию. Кто-нибудь может предложить мне какие-нибудь решения, чтобы сделать его лучше?

Ответы [ 3 ]

5 голосов
/ 31 марта 2010

Использование:

   SELECT c.customer_id
        , c.customer_nm
        , y.comment
     FROM CUSTOMER c
LEFT JOIN (SELECT od.customer_id,
                  MAX(od.orderdate) AS max_date
             FROM ORDERDETAIL od
         GROUP BY od.customer_id) x ON x.customer_id = c.customer_id
     JOIN (SELECT od.customer_id,
                  od.comment,
                  od.orderdate
             FROM ORDERDETAIL od) y ON y.customer_id = c.customer_id
                                   AND y.orderdate = x.max_date

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

0 голосов
/ 28 июня 2016

В зависимости от размера вашей базы данных, использование OUTER APPLY может быть намного быстрее, чем решение, предоставляемое @OMG Ponies:

SELECT c.customer_id
, c.customer_nm
, y.comment
FROM customer c
OUTER APPLY (
    SELECT TOP 1 o.comment
    FROM orderdetail o
    WHERE o.customer_id = c.customer_id
    ORDER BY orderDate DESC
) AS y

См. Планы выполнения запроса ниже. Обратите внимание на стоимость запроса относительно пакета (верхний план - OUTER APPLY, нижний план - решение @OMG Ponies; другие запросы в пакете вставляются во временные таблицы):

query execution plans

0 голосов
/ 31 марта 2010

У вас есть правильные показатели?

  • custoemr.customer_id

  • orderDetail.customer_id

оба должны быть проиндексированы. Как и должно быть oder.OrderDate. Без индексов вы выполняете табличное сканирование в изобилии - и вы ничего не говорите о ПОЧЕМУ ваш запрос медленный, поэтому я обычно делаю плохую индексацию.

Мне показалось забавным, что customer_id указан в деталях заказа, а не в заказе - обычно заказы назначаются одному клиенту.

Теперь, в корне неверно:

Функция GetLatestOrderByCustomer не делает этого;) Существует TOP 1, но нет - ORDER BY. Результаты SQL не имеют определенного порядка, если вы не говорите об этом, поэтому один возвращаемый элемент по существу - СЛУЧАЙНЫЙ.

Если customer_id является растущим числом, нет необходимости иметь функцию. Избавьтесь от этого и объедините часть запроса с основным SQL-запросом - это позволит оптимизатору запросов работать лучше.

Тогда - поля id не должны быть строками. Серьезно - вы взрываете представление там, большое время. Сделайте их маленькими, эффективными. int, smallint. Не используйте их для кодирования «конечного пользователя» (номер счета и т. Д.) - это может быть отдельное строковое поле с уникальным индексом. Но объединение строк, особенно определяемое как varchar (255), происходит довольно медленно по сравнению с объединениями в целых.

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