为什么这个查询在SQL Server中执行这么长时间?

时间:2017-01-21 08:52:58

标签: sql-server stored-procedures query-optimization

我想减少执行时间。这是我的疑问:

SELECT 
    StoreID,
    ItemLookupCode,
    sum(TotalQuantity) TotalQuantity,
    sum(ExtendedPrice) ExtendedPrice,
    sum(ExtendedCost) ExtendedCost
FROM 
    [HQMatajer].[dbo].[JCF_ItemDailySalesParent]
WHERE
    time >= CONVERT(DATETIME, '2015-01-01 00:00:00', 102) AND
    time <= CONVERT(DATETIME, '2015-12-31 00:00:00', 102)
GROUP BY 
    ItemLookupCode, StoreID

3分33秒执行此查询。该表中的记录总数 8百万。从数据库中检索的总记录行数 87,000

我为所有列创建了索引。

表格定义

[StoreID]             [nchar](150)      NOT NULL,
[ItemLookupCode]      [nvarchar](25)    NULL,
[ExtendedDescription] [varchar](3000)   NULL,
[DepartmentID]        [int]             NULL,
[DepartmentName]      [nvarchar](30)    NULL,
[CategoryID]          [int]             NULL,
[CategoryName]        [nvarchar](30)    NULL,
[SupplierID]          [int]             NULL,
[SupplierCode]        [nvarchar](17)    NULL,
[SupplierName]        [nvarchar](30)    NULL,
[Time]                [datetime]        NOT NULL,
[TotalQuantity]       [float]           NULL,
[ExtendedPrice]       [float]           NULL,
[ExtendedCost]        [float]           NULL`

索引定义

CREATE NONCLUSTERED INDEX [JCF_AllColumns] ON [dbo].[JCF_ItemDailySalesParent]
(
[Time]                ASC,
[ItemLookupCode]      ASC,
[StoreID]             ASC,
[ExtendedDescription] ASC,
[DepartmentID]        ASC,
[DepartmentName]      ASC,
[CategoryID]          ASC,
[CategoryName]        ASC,
[SupplierID]          ASC,
[SupplierCode]        ASC,
[SupplierName]        ASC,
[TotalQuantity]       ASC,
[ExtendedPrice]       ASC,
[ExtendedCost]        ASC
)

我正在使用SQL Server 2012。

3 个答案:

答案 0 :(得分:2)

无需在每列上编制索引,请尝试使用此索引:

    CREATE NONCLUSTERED INDEX [JCF_AllColumns] ON [dbo].[JCF_ItemDailySalesParent]
    (
    [Time]                ASC,
    [TotalQuantity]       ASC,
    [ExtendedPrice]       ASC,
    [ExtendedCost]        ASC
    )
    INCLUDE(
    [ItemLookupCode]  ,
    [StoreID]             
)

在WHERE子句中,您不需要CONVERT函数,这应该可以。

SELECT 
    StoreID,
    ItemLookupCode,
    sum(TotalQuantity) TotalQuantity,
    sum(ExtendedPrice) ExtendedPrice,
    sum(ExtendedCost) ExtendedCost
FROM 
    [HQMatajer].[dbo].[JCF_ItemDailySalesParent]
WHERE
    time >= '20150101' AND
    time <= '20151231'
GROUP BY 
    ItemLookupCode, StoreID

[StoreID]列必须是NCHAR吗?除非商店ID长度为150个字符,否则应将列更改为NVARCHAR,然后重建索引。

答案 1 :(得分:1)

尝试按如下方式创建索引:

CREATE NONCLUSTERED INDEX [JCF_foo] ON [dbo].[JCF_ItemDailySalesParent] (
    [Time],
    [StoreID],
    [ItemLookupCode]
) INCLUDE (
    [TotalQuantity],
    [ExtendedPrice],
    [ExtendedCost]
)

这应该使优化器能够使用仅索引查询。

也可以试试这个,这可以实现分组:

CREATE NONCLUSTERED INDEX [JCF_foo] ON [dbo].[JCF_ItemDailySalesParent] (
    [StoreID],
    [ItemLookupCode],
    [Time]
) INCLUDE (
    [TotalQuantity],
    [ExtendedPrice],
    [ExtendedCost]
)

答案 2 :(得分:0)

您已创建数据类型,可以避免使用nchar类型。您只在 StoreID 上存储号码。它只有四位数。

  

[StoreID] [nchar](150) NOT NULL

     

将数据类型更改为varchar(10)。 nchar是unicode格式。它会使大小加倍。除了你把 nchar的大小是150 。这将为所有字符创建一个记忆,即使你不使用超过4个字符。

     

由于nchar(150)的大小,它将在索引(不需要的b-tree页面)上创建多个页面

因此改为以下约束

  

[StoreID] [varchar](10) NOT NULL

     

并创建以下索引

     

CREATE NONCLUSTERED INDEX [JCF_AllColumns] ON [dbo].[JCF_ItemDailySalesParent] ( [Time] ASC, [TotalQuantity] ASC, [ExtendedPrice] ASC, [ExtendedCost] ASC ) INCLUDE( [ItemLookupCode] , [StoreID]
)