1

我有一张带有这种结构和索引的表

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 时,它需要十分钟或更长时间。如何优化结构或查询。请帮我。谢谢大家。

4

1 回答 1

0

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

  • 删除每个in clause. select ... from ... where a in (select ...)a) 非常非常慢,b) 很危险,因为它会使您的 sql server 内存不足——尤其是对于像你这样的大型数据集。您必须将所有 in 子句更改为left outer joins,这很容易做到。
  • 删除distinct clause. 这会强制您的查询按(在程序后面)进行排序,并且通常也很慢。尝试改写您的查询,以便记录已经不同
  • 只要您有不同的数据,您还必须更改unionunion all. 联合与distinct union我之前的声明相同。如果您使用union all,您将看到查询的巨大改进......只要您可以使您的数据不需要区分......

如果您设法在之前的 3 个更改中至少进行 2 个更改,我认为您会看到很大的改进。如果你能处理所有这些,你将有一个非常快速的查询。

而且,不要费心将您的 sql exec 更改为“预编译”存储过程。我认为这样做不会使您获得显着改善(我看到您在哪里有动态,因此无论如何这都不是申请人)。

请告诉我这是否有效。

于 2012-12-26T00:19:06.467 回答