如何优化T-SQL查询

时间:2011-08-15 10:23:52

标签: asp.net sql-server tsql

我正在编写一个T-SQL查询,我正在开发电子商务网站,因为我使用了4个主要表:

  1. 产品分类
  2. 产品
  3. 的OrderLineItem
  4. 顺序
  5. 我的管理部分有一个页面用于管理订单,现在我想按ProductCategory进行过滤,即Order包含Product(我的productId是在OrderLineItem表格中)与选定的ProductCategory相关,我通过以下查询执行此操作:

    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  
    

    我的此查询返回正确的结果,但查询每次都超时,任何人都可以告诉我如何优化此查询,以便不会超时吗?

    以下是表架构:

    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]
    

    产品表:

    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表:

    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表:

    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]
    

3 个答案:

答案 0 :(得分:1)

首先要做的几件事:

  1. 定义连接上的索引和列的位置。
  2. 从较小的表加入较大的表。
  3. 我建议您阅读有关表现以及如何找到原因的内容 - 这是一篇关于此主题的好文章:part 1part 2

答案 1 :(得分:0)

首先尝试延长超时以查看它是否有效。而不是在你的执行计划中获取战利品。将包含较少元素的表移动到连接的左侧。

答案 2 :(得分:0)

这未经过测试,因此我不确定它是否仍然符合您的查询要求。

它将获取Order的{​​{1}} OrderLineItem Product CategoryID等于@CategoryID或子类别@CategoryID {1}}。

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)

关于性能,你只需要对其进行测试即可找到答案。

索引是一件好事,您应该确保在外键列上有索引。