如何减少sql server查询时间

时间:2014-02-20 00:00:34

标签: sql sql-server sql-server-2008

我正在使用inner join运行查询。我用来进行聚合(SUM)的表上创建了索引,列名为dbo.tb_Sub_Contract.ContractGeneratedNo

任何表的最大行数约为250条记录。查询需要很长时间才能执行,如何减少执行时间???

SELECT 
   dbo.tb_Sub_Contract.ContractGeneratedNo, 
   SUM(dbo.tb_Sub_Contract.GrossAmount) AS GrossTotalAmount, 
   SUM(dbo.tb_Sub_Contract.WithheldAmount) AS WithheldTotalAmount, 
   dbo.tb_General_Contract.FilingMonth, 
   dbo.tb_General_Contract.FromSequenceNo, 
   dbo.tb_General_Contract.BoxNo, 
   CAST(dbo.tb_General_Contract.CompanyTRN AS Varchar(20)) + '-' + CAST(ISNULL(dbo.tb_General_Contract.CompanyBranch, '') AS Varchar(2)) AS Company_TRN_Branch, 
   COUNT(dbo.tb_Sub_Contract.SubContractId) AS NumberofContractors, 
   dbo.Get_Company_Name(CAST(dbo.tb_General_Contract.CompanyTRN AS Varchar(20)) + '-' + CAST(ISNULL(dbo.tb_General_Contract.CompanyBranch, '') AS Varchar(2))) AS Taxpayer_Name, 
   dbo.tb_General_Contract.PostedDate, 
   dbo.tb_Station.Collectorate, 
   dbo.tb_Station.StationCode
FROM         
   dbo.tb_General_Contract 
INNER JOIN
   dbo.tb_Sub_Contract ON dbo.tb_General_Contract.ContractGeneratedNo = dbo.tb_Sub_Contract.ContractGeneratedNo 
INNER JOIN
   dbo.tb_Station ON dbo.tb_General_Contract.StationId = dbo.tb_Station.StationCode
WHERE     
   (dbo.tb_Sub_Contract.IsActive = 1) AND (dbo.tb_General_Contract.IsActive = 1)
GROUP BY 
   dbo.tb_Sub_Contract.ContractGeneratedNo, dbo.tb_General_Contract.FilingMonth, 
   dbo.tb_General_Contract.FromSequenceNo, dbo.tb_General_Contract.BoxNo, 
   dbo.tb_General_Contract.CompanyTRN, dbo.tb_General_Contract.CompanyBranch, 
   dbo.tb_General_Contract.PostedDate, dbo.tb_Station.Collectorate, 
   dbo.tb_Station.StationCode

请参阅下面聚合中使用的表的两种表结构

CREATE TABLE [dbo].[tb_Sub_Contract](
    [SubContractId] [bigint] IDENTITY(1,1) NOT NULL,
    [ContractGeneratedNo] [varchar](100) NOT NULL,
    [ContractTypeId] [int] NOT NULL,
    [SubContractorName] [varchar](255) NOT NULL,
    [PeriodBegin] [datetime] NOT NULL,
    [PeriodEnd] [datetime] NOT NULL,
    [GrossAmount] [decimal](14, 2) NOT NULL,
    [WithheldAmount] [decimal](14, 2) NOT NULL,
    [WithheldAmount_Cal] [decimal](14, 2) NOT NULL,
    [trn_nbr] [bigint] NULL,
    [ActionTakenId] [int] NULL,
    [PostedBy] [bigint] NULL,
    [PostedDate] [datetime] NULL,
    [ModifiedBy] [bigint] NULL,
    [ModificationDate] [datetime] NULL,
    [IsActive] [bit] NULL,
    [trn_nbrBranch] [smallint] NULL,
 CONSTRAINT [PK_tb_Sub_Contract] PRIMARY KEY CLUSTERED 
(
    [SubContractId] 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].[tb_General_Contract](
    [ContractId] [bigint] IDENTITY(1,1) NOT NULL,
    [ContractGeneratedNo] [varchar](100) NULL,
    [CompanyTRN] [bigint] NULL,
    [CompanyBranch] [smallint] NULL,
    [FilingMonth] [datetime] NULL,
    [FromSequenceNo] [varchar](50) NULL,
    [BoxNo] [varchar](50) NULL,
    [ActionTakenId] [int] NULL,
    [PostedBy] [bigint] NULL,
    [PostedDate] [datetime] NULL,
    [IsActive] [bit] NULL,
    [ModifiedBy] [bigint] NULL,
    [ModificationDate] [datetime] NULL,
    [StationId] [char](3) NULL,
    [StationIdFrom] [char](3) NULL,
 CONSTRAINT [PK_tb_General_Contract] PRIMARY KEY CLUSTERED 
(
    [ContractId] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

2 个答案:

答案 0 :(得分:2)

使用表别名可以使您的查询更容易阅读。

为连接和过滤(WHERE子句)中使用的字段添加索引将大大提高性能。

设计索引有很多资源,例如:SQL Server Index Guide

语法示例:

CREATE CLUSTERED INDEX idx_ContractGeneratedNo ON tb_General_Contract (ContractGeneratedNo)
CREATE NONCLUSTERED INDEX idx_station ON tb_General_Contract (StationID)
....

这是格式化建议:

SELECT  SC.ContractGeneratedNo
      , SUM(SC.GrossAmount) AS GrossTotalAmount
      , SUM(SC.WithheldAmount) AS WithheldTotalAmount
      , GC.FilingMonth
      , GC.FromSequenceNo
      , GC.BoxNo
      , CAST(GC.CompanyTRN AS VARCHAR(20)) + '-'+ CAST(ISNULL(GC.CompanyBranch, '') AS VARCHAR(2)) AS Company_TRN_Branch
      , COUNT(SC.SubContractId) AS NumberofContractors
      , Get_Company_Name(CAST(GC.CompanyTRN AS VARCHAR(20))+ '-'+ CAST(ISNULL(GC.CompanyBranch,'') AS VARCHAR(2))) AS Taxpayer_Name
      , GC.PostedDate
      , S.Collectorate
      , S.StationCode
FROM    tb_General_Contract GC
INNER JOIN tb_Sub_Contract SC
    ON GC.ContractGeneratedNo = SC.ContractGeneratedNo
INNER JOIN tb_Station S
    ON GC.StationId = S.StationCode
WHERE   ( SC.IsActive = 1 )
        AND ( GC.IsActive = 1 )
GROUP BY SC.ContractGeneratedNo
      , GC.FilingMonth
      , GC.FromSequenceNo
      , GC.BoxNo
      , GC.CompanyTRN
      , GC.CompanyBranch
      , GC.PostedDate
      , S.Collectorate
      , S.StationCode

答案 1 :(得分:0)

您可以通过按列减少组来大大缩短查询时间。这可以通过ContractGeneratedNo对tb_Sub_Contract聚合进行分组,然后将该数据集连接到tb_General_Contract表来完成:

select
    sc.ContractGeneratedNo,
    sc.GrossTotalAmount,
    sc.WithheldTotalAmount,
    gc.FilingMonth,
    gc.FromSequenceNo,
    gc.BoxNo, 
    cast(gc.CompanyTRN as varchar(20)) + '-' + cast(isnull(gc.CompanyBranch, '') as varchar(2)) Company_TRN_Branch,
    sc.NumberofContractors,
    dbo.Get_Company_Name(cast(gc.CompanyTRN as varchar(20)) + '-' + cast(isnull(gc.CompanyBranch, '') as varchar(2))) as Taxpayer_Name,
    gc.PostedDate,
    s.Collectorate,
    s.StationCode
from dbo.tb_General_Contract gc
    inner join  (
                select
                    ContractGeneratedNo,
                    sum(GrossAmount) GrossTotalAmount,
                    sum(WithheldAmount) WithheldTotalAmount,
                    count(SubContractId) NumberofContractors
                from dbo.tb_Sub_Contract
                where IsActive = 1
                group by
                    ContractGeneratedNo
                ) sc
        on gc.ContractGeneratedNo = sc.ContractGeneratedNo
    inner join dbo.tb_Station
        on gc.StationId = s.StationCode
where
    gc.IsActive = 1