2011-08-15 39 views
5

Tôi viết một truy vấn T-SQL, tôi đang phát triển các trang web thương mại điện tử, trong đó tôi đang sử dụng 4 bảng chính:Làm thế nào để tối ưu hóa các truy vấn T-SQL

  1. ProductCategory
  2. sản phẩm
  3. OrderLineItem
  4. tự

tôi có một trang trong phần admin của tôi cho quản lý các đơn đặt hàng, Bây giờ tôi muốn lọc theo ProductCategory tức mà 01.236.chứa Product (tôi productId là trong OrderLineItem bảng) có liên quan đến các lựa chọn ProductCategory, tôi đang làm điều này qua bên dưới truy vấn:

SELECT 
    O.OrderID,O.[OrderDate],O.[StatusID]       
FROM [Order] O        
INNER JOIN [Dyve_User] U ON U.[UserID] = O.[UserID]        
INNER JOIN (SELECT OD.OrderID 
      FROM OrderLineItem OD 
      LEFT OUTER JOIN [Product] P ON OD.ProductID = P.ProductID 
      LEFT OUTER JOIN [ProductCategory] PC ON PC.CategoryID = P.CategoryID 
      WHERE 
       (P.CategoryID = COALESCE(@CategoryID, P.CategoryID)        
       OR P.CategoryID IN (SELECT CategoryID 
            FROM ProductCategory        
            WHERE ParentID = COALESCE(@CategoryID, ParentID) 
            ) 
       )        
      ) AS T ON O.OrderID = T.OrderID 

tôi truy vấn này trả lại kết quả chính xác nhưng lần truy vấn ra mọi thời gian, bất cứ ai có thể cho tôi biết làm thế nào để tối ưu hóa truy vấn này để điều này sẽ không thời gian ra?

Sau đây là sơ đồ bảng:

CREATE TABLE [dbo].[Order](
[OrderID] [int] IDENTITY(1,1) NOT NULL, 
[OrderDate] [datetime] NULL, 
[OrderTax] [money] NULL, 
[OrderTotal] [money] NULL, 
[ShippingCharge] [money] NULL, 
[TrackingNumber] [varchar](50) NULL, 
[TransactionStatusID] [int] NULL, 
[UserID] [int] NULL, 
[PromotionCode] [varchar](50) NULL 
[ExpiryDate] [datetime] NULL, 
[PaymentType] [tinyint] NULL 
    CONSTRAINT [Order_PK] PRIMARY KEY CLUSTERED 
    (
[OrderID] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,   ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 

Bảng sản phẩm:

CREATE TABLE [dbo].[Product](
[ProductID] [int] IDENTITY(1,1) NOT NULL, 
[CategoryID] [int] NULL, 
[ProductName] [nvarchar](600) NULL, 
[ManufacturerID] [int] NULL, 
[UnitPrice] [money] NULL, 
[RetailPrice] [money] NULL, 
[IsOnSale] [bit] NOT NULL, 
[ExpiryDate] [datetime] NULL, 
[IsElectrical] [bit] NULL, 
[IsActive] [bit] NULL, 
[ProductType] [int] NULL, 
[AllowBackOrder] [bit] NULL 
    CONSTRAINT [Product_PK] PRIMARY KEY CLUSTERED 
    (
[ProductID] ASC 
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,  ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
    ) ON [PRIMARY] 

ProductCategory Bảng:

CREATE TABLE [dbo].[ProductCategory](
[CategoryID] [int] IDENTITY(1,1) NOT NULL, 
[Name] [nvarchar](100) NOT NULL, 
[Description] [nvarchar](max) NULL, 
[ParentID] [int] NULL, 
[IsActive] [bit] NULL 
    CONSTRAINT [ProductCategory_PK] PRIMARY KEY CLUSTERED 
    (
[CategoryID] ASC 
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,  ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 

OrderLineItem Bảng:

CREATE TABLE [dbo].[OrderLineItem](
[OrderDetailID] [int] IDENTITY(1,1) NOT NULL, 
[OrderID] [int] NOT NULL, 
[ProductID] [int] NOT NULL 
[TotalPrice] [money] NULL, 
[Quantity] [int] NULL, 
[Discount] [money] NULL, 
[UnitPrice] [money] NULL, 
[UserID] [int] NULL, 
    CONSTRAINT [OrderLineItem_PK] PRIMARY KEY CLUSTERED 
     (
[OrderDetailID] ASC 
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,  ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
    ) ON [PRIMARY] 
+0

Tại sao bạn làm LEFT JOIN ở đây nếu bạn chỉ muốn xem các sản phẩm từ danh mục cụ thể? FROM OrderLineItem OD LEFT OUTER JOIN [ProductCategory] PC TRÊN PC.CategoryID = P.CategoryID WHERE (P.CategoryID = COALESCE (@CategoryID, P.CategoryID) – sll

Trả lời

0

Điều này không được kiểm tra vì vậy tôi không chắc liệu nó vẫn làm những gì bạn dự định với truy vấn của mình.

Nó sẽ lấy Order s có một OrderLineItem với một Product với một CategoryID đó là bằng @CategoryID hoặc một loại trẻ @CategoryID.

SELECT O.OrderID, 
     O.[OrderDate], 
     O.[StatusID] 
FROM [Order] AS O 
WHERE O.OrderID IN (SELECT OD.OrderID 
        FROM OrderLineItem AS OD 
          INNER JOIN Product AS P 
           ON OD.ProductID = P.ProductID 
          INNER JOIN (SELECT PC.CategoryID 
             FROM ProductCategory 
             WHERE ParentID = @CategoryID 
             UNION ALL 
             SELECT @CategoryID) AS C 
           ON P.CategoryID = C.CategoryID) 

Về hiệu suất, bạn chỉ cần kiểm tra để tìm hiểu.

Chỉ mục là một điều tốt và bạn nên đảm bảo rằng bạn có chỉ mục trên các cột khóa ngoài.

+0

Tôi đã thử theo cách này nhưng gặp cùng Lỗi thời gian, vui lòng đề xuất cho tôi bất kỳ cách nào khác – Vijjendra

+0

@Vijjendra - Có thể hữu ích nếu bạn có thể cập nhật câu hỏi của mình với cấu trúc bảng (DDL) bao gồm bất kỳ chỉ mục nào, bao nhiêu hàng mỗi bảng chứa và số lượng hàng bạn mong muốn được trả về với q này uery. Bạn đã thử chạy truy vấn trong SSMS chưa? –

+0

Tôi đã cập nhật câu hỏi của mình với Giản đồ bảng. – Vijjendra

1

Một vài điều cần bắt đầu với:

  1. Xác định chỉ mục trên tham gia và vị trí cột.
  2. Tham gia từ các bảng nhỏ hơn đến các bảng lớn hơn.

Tôi khuyên bạn nên đọc về hiệu suất và cách tìm nguyên nhân - đây là một bài viết hay về chủ đề: part 1part 2.

+0

ý của bạn là gì Tham gia từ các bảng nhỏ hơn đến các bảng lớn hơn? ? – Vijjendra

+0

@Vijjendra - Bắt đầu với các bảng có ít dữ liệu hơn và tham gia vào các bảng lớn hơn – Oded

0

Trước tiên, hãy thử thời gian chờ lâu hơn để xem nó hoạt động. Hơn là loot tại kế hoạch thực hiện của bạn. Di chuyển các bảng có ít phần tử hơn bên trái của phép nối.

+0

Làm thế nào để di chuyển các bảng có ít thành phần bên trái của kết nối? – Vijjendra

+0

Đây là những gì @Oded nhận xét "Bắt đầu với các bảng có ít dữ liệu hơn và tham gia vào các bảng lớn hơn " –

Các vấn đề liên quan