多少数据来优化我们的查询

时间:2012-12-25 08:54:24

标签: sql-server sql-server-2008 tsql sql-server-2008-r2 query-optimization

我有一个包含此结构和索引的表

CREATE TABLE [dbo].[Report4](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [Mesc] [nvarchar](50) NULL,
    [Line] [nvarchar](5) NULL,
    [Unit] [nvarchar](5) NULL,
    [Description] [nvarchar](500) NULL,
    [ST_CODE] [nvarchar](5) NULL,
    [PbsNo] [nvarchar](50) NULL,
    [PbsDate] [nvarchar](10) NULL,
    [PbsQty] [nvarchar](10) NULL,
    [PbsQtyRec] [nvarchar](10) NULL,
    [QtyConsum1] [nvarchar](10) NULL,
    [QtyConsum2] [nvarchar](10) NULL,
    [QtyConsum3] [nvarchar](10) NULL,
    [QtyConsum4] [nvarchar](10) NULL,
    [QtyConsum5] [nvarchar](10) NULL,
    [Type] [nvarchar](20) NULL,
    [InvQty] [nvarchar](10) NULL,
    [TypeRequest] [nvarchar](50) NULL,
    [HeaderId] [bigint] NULL,
    [LOCATION] [nvarchar](10) NULL,
 CONSTRAINT [PK_Report4] PRIMARY KEY CLUSTERED
(
    [Id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
CREATE NONCLUSTERED INDEX [HeaderId] ON [dbo].[Report4]
(
    [HeaderId] ASC
)
INCLUDE ( [Id],
[Mesc],
[Line],
[Unit],
[Description],
[ST_CODE],
[PbsNo],
[PbsDate],
[PbsQty],
[PbsQtyRec],
[QtyConsum1],
[QtyConsum2],
[QtyConsum3],
[QtyConsum4],
[QtyConsum5],
[Type],
[InvQty],
[TypeRequest]) WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
GO
CREATE NONCLUSTERED INDEX [HeaderIdRAll] ON [dbo].[Report4]
(
    [HeaderId] ASC
)
INCLUDE ( [Id],
[Mesc],
[Line],
[Unit],
[Description],
[ST_CODE],
[PbsNo],
[PbsDate],
[PbsQty],
[PbsQtyRec],
[QtyConsum1],
[QtyConsum2],
[QtyConsum3],
[QtyConsum4],
[QtyConsum5],
[Type],
[InvQty],
[TypeRequest]) WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
GO
CREATE NONCLUSTERED INDEX [LineNOIRHeaderId] ON [dbo].[Report4]
(
    [Line] ASC
)
INCLUDE ( [HeaderId])
WHERE ([line]='I')
WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
GO
CREATE NONCLUSTERED INDEX [LineNoRHeaderId] ON [dbo].[Report4]
(
    [Line] ASC
)
INCLUDE ( [HeaderId])
WHERE ([line]='H')
WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
GO
CREATE NONCLUSTERED INDEX [LineNoRMesc] ON [dbo].[Report4]
(
    [Line] ASC
)
INCLUDE ( [Mesc])
WHERE ([line]='I')
WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
GO
CREATE NONCLUSTERED INDEX [MescRAll] ON [dbo].[Report4]
(
    [Mesc] ASC
)
INCLUDE ( [Id],
[Line],
[Unit],
[Description],
[ST_CODE],
[PbsNo],
[PbsDate],
[PbsQty],
[PbsQtyRec],
[QtyConsum1],
[QtyConsum2],
[QtyConsum3],
[QtyConsum4],
[QtyConsum5],
[Type],
[InvQty],
[TypeRequest],
[HeaderId]) WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
GO

我想为此表运行此查询

ALTER PROCEDURE [dbo].[SPSelectReport2] (@StringWhereParameter nvarchar(4000),@PageIndex int,@PageSize int )
AS
BEGIN

    SET NOCOUNT ON;

-- َ Begin Of Transaction
begin tran

declare @from int=(@PageSize*(@PageIndex-1))+1
declare @to int=(@PageIndex*@PageSize)

declare @Query nvarchar(max)
set @Query=' select 

distinct id, [Mesc], [Line]
      ,[Unit]
      ,[Discription]
      ,[InvQty]
      ,[LastDateNil]
      ,[StCode]
      ,[PlanCode]
      ,[MIN]
      ,[MAX]
      ,[LastDateConsum]
      ,[PbsNo]
      ,[PbsDate]
      ,[PbsQty]
      ,[PbsQtyRec]
      ,[DateDelay]
      ,[TypeRequest]
      ,[HeaderId]
      ,LOCATION
 from (

SELECT *, ROW_NUMBER() OVER(ORDER BY Id) ROW_NUM
  FROM(
((SELECT Id,[Mesc]
      ,[Line]
      ,[Unit]
      ,[Discription]
      ,[InvQty]
      ,[LastDateNil]
      ,[StCode]
      ,[PlanCode]
      ,[MIN]
      ,[MAX]
      ,[LastDateConsum]
      ,[PbsNo]
      ,[PbsDate]
      ,[PbsQty]
      ,[PbsQtyRec]
      ,[DateDelay]
      ,[TypeRequest]
      ,[HeaderId]
      ,LOCATION
  FROM [MyMaterialDB].[dbo].[Report2]
  WHERE headerid IN(SELECT HeaderId FROM [MyMaterialDB].[dbo].[Report2] WHERE line=''H'''+ @StringWhereParameter+'))
  UNION
  (
    (SELECT Id,[Mesc]
      ,[Line]
      ,[Unit]
      ,[Discription]
      ,[InvQty]
      ,[LastDateNil]
      ,[StCode]
      ,[PlanCode]
      ,[MIN]
      ,[MAX]
      ,[LastDateConsum]
      ,[PbsNo]
      ,[PbsDate]
      ,[PbsQty]
      ,[PbsQtyRec]
      ,[DateDelay]
      ,[TypeRequest]
      ,[HeaderId]
      ,LOCATION
  FROM [MyMaterialDB].[dbo].[Report2]
  WHERE mesc IN(SELECT mesc FROM [MyMaterialDB].[dbo].[Report2] WHERE line=''I''' +@StringWhereParameter+'))
  UNION
  (SELECT Id, [Mesc]
      ,[Line]
      ,[Unit]
      ,[Discription]
      ,[InvQty]
      ,[LastDateNil]
      ,[StCode]
      ,[PlanCode]
      ,[MIN]
      ,[MAX]
      ,[LastDateConsum]
      ,[PbsNo]
      ,[PbsDate]
      ,[PbsQty]
      ,[PbsQtyRec]
      ,[DateDelay]
      ,[TypeRequest]
      ,[HeaderId]
      ,LOCATION
  FROM [MyMaterialDB].[dbo].[Report2]
  WHERE mesc IN(SELECT HeaderId FROM [MyMaterialDB].[dbo].[Report2] WHERE line=''I'''+@StringWhereParameter+')
  )))) a)b where b.ROW_NUM between '+CAST(@from as varchar(10))+' and '+CAST(@to as varchar(10))

  -- Order by Mesc,Line,unit
 exec(@Query)
 --print @Query

--


 if @@error = 0    
 Commit Tran    
 Else   
 rollback tran
End

进入此表我有超过1000000条记录,当运行此sp时,需要十分钟或更长时间。如何优化结构或查询。请帮我。谢谢大家。

1 个答案:

答案 0 :(得分:0)

对于初学者,您必须执行以下操作(我认为只有那些操作可以将您的查询执行时间缩短到不到一分钟):

  • 删除每in clauseselect ... from ... where a in (select ...)是a)非常非常慢,b)危险,因为它可以运行你的sql server内存 - 特别是像你的大型数据集 - 。您必须将所有条款更改为left outer joins,这样做非常容易。
  • 删除distinct clause。这会强制您的查询按(在示意图后面)执行排序,并且通常也非常慢。尝试重新编写您的查询,以便记录已经不同
  • 只要您拥有不同的数据,您还必须将union更改为union all。联盟与distinct union相同,这与我之前的陈述相同。如果您使用union all,您的查询会有很大的改进...只要您可以将数据带到不需要的地方......

如果您设法在之前的3次更改中设置至少2次,我认为您会看到很大改进。如果您可以处理所有这些问题,那么查询速度非常快。

而且,不要费心将sql exec更改为“预先编译的”存储过程。我认为你不会通过这样做获得显着改善(我认为你有动态,所以在任何情况下这都不是申请人)。

请告诉我这是否有效。